目录
[一、利用 JSON 字符串 返回数据](#一、利用 JSON 字符串 返回数据)
[二、nodmon 工具 自动重启服务](#二、nodmon 工具 自动重启服务)
[三、IE 缓存问题](#三、IE 缓存问题)
[三、AJAX 请求超时 / 网络异常处理](#三、AJAX 请求超时 / 网络异常处理)
[四、AJAX 取消请求](#四、AJAX 取消请求)
[五、AJAX 请求重复发送问题](#五、AJAX 请求重复发送问题)
一、利用 JSON 字符串 返回数据
利用 AJAX 向服务端发送请求,服务端向我们返回的一般都是 JSON 格式的数据
在 div 中按键 向服务端发出请求 并在 div 中渲染返回结果
和前面类似不多解释了,不明白细节可以看上一篇
(一)基础代码
AJAX 前端代码:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AJAX POST 请求</title>
</head>
<style>
#result {
width: 200px;
height: 100px;
border: solid pink 1px;
}
</style>
<body>
<div id="result"></div>
<script>
// 获得元素对象
const result = document.getElementById("result")
// 绑定键盘按下事件
window.onkeydown = function () {
// 创建对象
const xhr = new XMLHttpRequest();
// 初始化设置请求方法 和url(就是发送的对象)
xhr.open('GET', 'http://127.0.0.1:8000/json-server')
// 设置请求头
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 自定义请求头
xhr.setRequestHeader('name', 'hahaha')
// 发送
xhr.send('a=100&b=200')
// 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function () {
// 在里面处理服务端返回的结果 在 4 时再处理
if (xhr.readyState === 4) {
// 判断响应的状态码 200 404 403 401 500
// 2 开头都表示成功
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response
}
}
}
}
</script>
</body>
</html>
服务端代码:
javascript
// 1、先引入 express 框架
const express = require('express')
// 2、然后创建应用对象
const app = express()
// 3、创建路由规则,函数里面有两个参数,分别是请求报文和响应报文的封装
app.all('/json-server', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 特殊响应头
response.setHeader('Access-Control-Allow-Headers', '*')
// 设置响应体
response.send('HELLO AJAX POST')
})
// 4、监听端口启动服务
app.listen(8000, () => {
console.log('服务已经启动,8000端口监听中...')
})
(二)原理及实现
我们想返回别的东西 不想只返回一堆字,比如说我们想返回一个对象 ,但是respond() 方法只能返回字符串,所以我们可以通过把 data 对象转换成 JSON 字符串的形式返回
javascript
const data = {
name: '一个人'
}
let str = JSON.stringify(data)
response.send(str)
结果展示:此时返回的是一个字符串
可以在前端代码中把字符串重新转换成对象
javascript
if (xhr.readyState === 4) {
// 判断响应的状态码 200 404 403 401 500
// 2 开头都表示成功
if (xhr.status >= 200 && xhr.status < 300) {
let data = JSON.parse(xhr.response)
console.log(data)
}
}
输出检验一下,确实是对象
但是上面属于手动转换,我们可以自动转换
加上一句下面就可以自动转换了
javascript
xhr.responseType = 'json'
成功
在页面中显示数据 就稍微改一下渲染一下就行
结果展示:
二、nodmon 工具 自动重启服务
(一)用途
可以让我们修改服务端代码时不用重新启动服务器,节省时间
(二)下载
我们直接 在没有服务端启动的情况下 在终端界面 输入
npm install -g nodemon 就能下载了
(三)使用
然后我们以后启动服务器时用
nodemon.cmd 服务器文件名.js 就行了
三、IE 缓存问题
(一)问题描述
IE 浏览器会对 AJAX 的请求结果做一个缓存,下一次再发送请求时,走的是本地的缓存而不是服务器返回的最新的数据,对于时效性比较强的场景,AJAX 的缓存会影响结果
如果修改服务端传回的内容 在 ie 浏览器中刷新 显示内容不会发生改变,因为 ie 是从本地缓存中取出的数据
(二)解决方法
代码如下:在 open 方法代码中的 url 后面加上 当前时间戳 这样每次点击 ie 浏览器收到的请求都不一样,ie 以为我们发送了一个新的请求,这样就不会从本地缓存中读取数据了
javascript
xhr.open('GET', 'http://127.0.0.1:8000/ie?t='+Date.now())
三、AJAX 请求超时 / 网络异常处理
(一)处理方法
我们不能保证服务端一直准确快速响应 AJAX 请求,我们可以通过给 AJAX 加一个超时的设置,给用户提醒,网络异常的时候也给用户提醒,让产品体验更好
我们可以在服务器中设置一个延时函数 3秒后返回 延时响应
javascript
setTimeout(() =>{
response.send('延时响应')
},3000)
在 AJAX 中设置一些代码 如果 2s 内还没返回请求就取消
javascript
xhr.timeout = 2000
超时回调,就是超时弹出对话框
javascript
xhr.ontimeout = function (){
alert('网络异常,稍后再试')
}
(二)完整代码
AJAX部分:
javascript
<script>
const btn = document.getElementsByTagName('button')[0]
const result = document.getElementById("result")
btn.addEventListener('click', function () {
const xhr = new XMLHttpRequest();
// 超时设置
xhr.timeout = 2000
// 超时回调
xhr.ontimeout = function () {
alert('网络异常,稍后再试')
}
xhr.onerror = function(){
alert('你的网络似乎出现了问题')
}
// 初始化设置请求方法 和url(就是发送的对象)
xhr.open('GET', 'http://127.0.0.1:8000/delay')
// 发送
xhr.send('')
// 事件绑定 处理服务端返回的结果
xhr.onreadystatechange = function () {
// 在里面处理服务端返回的结果 在 4 时再处理
if (xhr.readyState === 4) {
// 判断响应的状态码 200 404 403 401 500
// 2 开头都表示成功
if (xhr.status >= 200 && xhr.status < 300) {
result.innerHTML = xhr.response
}
}
}
})
</script>
服务端部分:
javascript
// 1、先引入 express 框架
const express = require('express')
// 2、然后创建应用对象
const app = express()
// 3、创建路由规则,函数里面有两个参数,分别是请求报文和响应报文的封装
app.all('/delay', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 特殊响应头
response.setHeader('Access-Control-Allow-Headers', '*')
// 设置响应体
setTimeout(() => {
response.send('hello ie')
}, 3000)
})
// 4、监听端口启动服务
app.listen(8000, () => {
console.log('服务已经启动,8000端口监听中...')
})
四、AJAX 取消请求
在我们通过 AJAX 向服务器发送请求时,在服务器返回数据前,我们可以通过代码手动取消请求
使用 abort 方法 属于 AJAX 对象
就如下面 使用 x.abort() 就能取消请求
注意下面用到前面 IE 缓存的问题 在 url 后面加上一个时间戳,会返回 304 错误,原本的内容会被服务器缓存接着用 注意一下
javascript
<script>
let x = null
const btns = document.querySelectorAll('button')
btns[0].onclick = function () {
x = new XMLHttpRequest();
x.open('GET', 'http://127.0.0.1:8000/delay?t='+Date.now())
x.send()
}
btns[1].onclick = function () {
x.abort()
}
</script>
取消请求的结果:
五、AJAX 请求重复发送问题
之前用户连续点击按钮 AJAX 一直向服务器发送请求,但是我们不想这么做,我们想让用户连续点击时 取消前一次发送,进行下一次发送 有点像 js 中的防抖,有利于性能提升
我们就加入一个标识变量 isSending 检测 是否发送请求,如果有请求就把之前的请求取消,然后设置 isSending 为 true 然后检测是否发送结束,如果服务器返回全部内容时 就是
xhr.readyState === 4 时就认定发送结束了,然后设置 isSending 为 false
不要判断响应的状态码 因为有可能这个请求有可能不成功 不是 2 开头 一直在成功里面判断isSending 就不能为 false了 不能继续进行下去了
javascript
<script>
let x = null
// 标识变量 看是否在发送 AJAX 请求
let isSending = false
const btns = document.querySelectorAll('button')
btns[0].onclick = function () {
// 判断标识符变量
if(isSending) x.abort()
x = new XMLHttpRequest();
// 修改 标识变量的值
isSending = true
x.open('GET', 'http://127.0.0.1:8000/delay?')
x.send()
xhr.onreadystatechange = function () {
// 在里面处理服务端返回的结果 在 4 时再处理
if (xhr.readyState === 4) {
// 判断响应的状态码 200 404 403 401 500
// 2 开头都表示成功
isSending = false
}
}
}
</script>