首页 > 其他分享 >AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理

时间:2022-12-19 21:32:05浏览次数:63  
标签:function document 请求 xhr AJAX let 超时 07

开发的产品上线后,难免会遇到请求超时或网络异常的情况,在客户端设置超时处理和异常提醒,可以提升用户体验。

手动取消请求和取消重复发送请求,可以节省服务端资源;

这篇,来实现这些需求;


搭建Web服务环境

之前讲过 Express 快速启动Web服务,需要复习的同学请看:

​AJAX(笔记03) - 原生AJAX - Node.js 和 Express 的简介、安装​


新建 server.js 服务端文件:

const express = require('express')
const app = express()
app.get('/delay', (request, response) => {
response.setHeader('Access-Control-Allow-Origin', '*')
setTimeout(() => {
response.send('Hello Ajax!')
}, 3000)
})
app.listen('8000', () => {
console.log('Web服务已经启动,端口8000监听中... ...');
})

提示:设置延迟3秒再发送数据的函数,模拟请求时长;

启用服务:

> nodemon server.js


创建前端AJAX

需求是点击按钮发送请求,获得服务器响应数据;

新建 ajax_delay.html ,写点结构样式

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#result{
width: 200px;
height: 100px;
border:1px solid #394;
}
</style>
</head>
<body>
<button>点击按钮发送请求</button>
<div id="result">

</div>
</body>
</html>

看下效果:

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理_AJAX

在当前文档里,写下ajax的JS部分;

let btn = document.getElementsByTagName('button')[0]
let res = document.getElementById('result')
btn.onclick = function(){
let xhr = new XMLHttpRequest();
xhr.open("GET","http://127.0.0.1:8000/delay")
xhr.send()
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status>=200 && xhr.status <300){
res.innerHTML = xhr.response
}
}
}
}

提示:由于服务端延迟3秒显示数据;

观察 Network 中的响应:

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理_重复请求_02

status 和 time 的状态是 pending ...  , 3秒过后显示结果:

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理_重复请求_03

status 状态码200,time 用时 3秒;


请求超时设置

let btn = document.getElementsByTagName('button')[0]
let res = document.getElementById('result')
btn.onclick = function(){
let xhr = new XMLHttpRequest();
// 超时设置2秒
xhr.timeout = 2000
xhr.open("GET","http://127.0.0.1:8000/delay")
xhr.send()
// ... 代码省略
}

提示:只需设置超时时长,超时后自动取消请求;

点击按钮看效果:

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理_AJAX_04

2秒后,自动取消请求;


请求超时回调

let btn = document.getElementsByTagName('button')[0]
let res = document.getElementById('result')
btn.onclick = function(){
let xhr = new XMLHttpRequest();
// 超时设置2秒
xhr.timeout = 2000
// 超时设置回调
xhr.ontimeout = function(){
console.log('请求超时了');
}
// .... 代码省略
}

提示:超时后会取消请求,并触发超时回调函数,在控制台输出提示信息;


网络异常回调

let btn = document.getElementsByTagName('button')[0]
let res = document.getElementById('result')
btn.onclick = function(){
let xhr = new XMLHttpRequest();
// 超时设置2秒
xhr.timeout = 2000
// 超时设置回调
xhr.ontimeout = function(){
console.log('请求超时了');
}
// 网络异常回调
xhr.onerror = function(){
console.log("请检查网络...");
}
// .... 代码省略
}

开发者工具可以模拟断线的情况:

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理_AJAX_05

点击按钮,查看效果:

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理_AJAX_06

结果显示失败(failed),控制台输出提示信息;


手动取消请求

这次增加个按钮用来取消请求,

<button>点击按钮发送请求</button>
<div id="result">

</div>
<button>点击按钮取消请求</button>

看下效果:

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理_AJAX_07

修改下前端代码:后端代码不用动;

// 获取元素对象
let btns = document.getElementsByTagName('button')
let res = document.getElementById('result')
let xhr = null
// 发起请求按钮
btns[0].onclick = function () {
xhr = new XMLHttpRequest();
xhr.open("GET", "http://127.0.0.1:8000/delay")
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
res.innerHTML = xhr.response
}
}
}
}
// 取消请求按钮
btns[1].onclick = function(){
xhr.abort()
}

提示:使用 xhr.abort() 方法来取消请求;

之所以把 xhr 定义在外面,是因为放在发起请求的按钮里面,那取消请求的按钮就调不到 xhr 对象了;

看下效果:

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理_重复请求_08

提示:连续3次发起请求,又手动取消请求;

status 的状态变化,发起请求时是 pending ... ,取消请求时是 canceled ... ;


重复发送请求

实际应用中,用户可能频繁点击按钮来重复获取数据,给服务器带来很大压力,如图:

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理_AJAX_09

服务端越是响应慢,用户点的越勤快,会造成很多重复请求;如果可以发现重复的请求时,把之前的请求 abort 掉,这样就不怕用户重复点击请求了;

可以设置一个开关,当请求的时候发现已有请求则中止请求;

let btn = document.getElementsByTagName('button')[0]
let res = document.getElementById('result')
let xhr = null
// 设置开关,代表是否正在发送请求
let isSending = false
btn.onclick = function () {
// 判断开关
if(isSending) xhr.abort()
xhr = new XMLHttpRequest();
// 发送请求前,打开开关
isSending = true
xhr.open("GET", "http://127.0.0.1:8000/delay")
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
// 关闭开关
isSending = false
if (xhr.status >= 200 && xhr.status < 300) {
res.innerHTML = xhr.response
}
}
}
}

提示:设置开关的作用是每当点击按钮就都要先判断一下当前是不是处在请求中。如果是,就 abort 掉,并开启一个新的请求;如果不是,就开启一个新的请求,并打开开关,直到响应状态完成后再关闭开关。

看下效果:

AJAX(笔记07) - 原生AJAX - 请求超时、网络异常、取消请求和重复请求处理_请求超时_10

这样的好处就节省了重复请求的资源。

标签:function,document,请求,xhr,AJAX,let,超时,07
From: https://blog.51cto.com/ahuiok/5953874

相关文章

  • Ajax
    Ajaxajax不是一门新的技术并且有很多版本,我们目前学习的是jQuery版本,各版本之间本质是一样的Ajax的特点是异步提交,局部刷新Ajax基本语法基本语法 $.ajax({ur......
  • SAP UI5 Mock Server 在响应 OData 请求时的单步调试
    SAPUI5中包含的模拟服务器模仿ODataV2后端调用。它模拟OData提供程序并且完全基于客户端,这意味着不需要与远程主机的网络连接。它拦截对服务器的HTTP调用,并向客......
  • Ajax
    目录AjaxContent-Typeajax携带文件数据Ajax异步提交局部刷新ajax不是一门新的技术并且有很多版本我们目前学习的是jQuery版本(版本无所谓本质一样就可以) 基本语......
  • Ajax
    目录AjaxContent-Typeajax携带文件数据Ajax异步提交,局部刷新基本语法$.ajax({url:'',#提交地址,与form标签的action一致type:'post',#请求......
  • Q查询进阶操作、 ORM查询优化 、ORM事务操作、 ORM常用字段类型、 ORM常用字段参数 、
    目录Q查询进阶操作ORM查询优化ORM事务操作ORM常用字段类型ORM常用字段参数AjaxContent-Typeajax携带文件数据Q查询进阶操作fromdjango.db.modelsimportQq_obj=Q()......
  • Ajax简述 —— 快速增量式响应
    AjaxAjax的简介及用法Ajax是指异步JS和XML,使用Ajax技术网页应用能够快速地将增量更新呈现在用户界面上,而不需要重载(刷新)整个页面,这使得程序能够更快地回应用户的操作。......
  • Spring处理跨域请求
    [nio-8080-exec-8]o.s.web.cors.DefaultCorsProcessor    :SkipCORSprocessing:requestisfromsameorigin一次正常的请求最近别人需要调用我们系统的某一个......
  • django ORM查询优化,事务,ajax
    ORM查询优化,事务,ajax内容概要Q查询进阶操作ORM查询优化ORM事务操作ORM常用字段类型ORM常用字段参数ORM三种创建多对多的方式Ajax请求内容详细Q查询进阶操作,默......
  • Ajax请求 content_type ajax发送Fromdata对象
    目录Ajax请求入门ajax实现简单计算器content_typeurlencodefromdataapplication/json自定义request.JSONajax发送Fromdata对象Ajax请求入门异步提交局部刷新ajax不是一......
  • ORM的一些尾巴和Ajax的基础
    今日内容详细Q查询进阶操作使用Q查询记得先导入fromdjango.db.modelsimportQ#1.先产生Q对象q_obj=Q()#2.默认多个条件的连接条件是and可以修改为orq_obj.c......