ajax、fetch、axios如何中断请求?
先来说一说“中断请求”的实际场景,当页面有多个tab页签时,每次切换页签都会去请求数据,频繁的切换就会去请求很多次,比如A页签切换到B页签,A页签请求完全是不必要的,这时候可以在切换时中断请求。
AbortController实验室功能,已经在主流浏览器实现,IE浏览器可以不支持,需要导入polyfill。
AbortController
接口表示一个控制器对象,允许你根据需要中止一个或多个 Web请求。官网参考:https://developer.mozilla.org...
1、axios
axios已经实现AbortController,具体实践如下:
// fontend
import React, { useEffect } from 'react';
import axios from 'axios';
const AbortController = () => {
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
useEffect(() => {
axios.post('http://127.0.0.1:8088/getData', {name: 'zs', pwd: '123456'}, {cancelToken: source.token})
.then(res => {
console.log(res);
})
}, []);
const abort = () => {
source.cancel('cancle request!');
}
return (
<>
<div>this is a abortController page.</div>
<div><button onClick={abort}>取消请求</button></div>
</>
)
}
export default AbortController;
// backend
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser')
const app = express();
app.use(cors({
origin: '*',
allowedHeaders: ['content-type'],
}))
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/getData', (req, res) => {
const {name, pwd} = req.body;
if (!name || !pwd) {
return res.json({
code: 200,
data: {},
errorMessage: '参数不能为空'
})
}
setTimeout(() => {
res.json({
code: 200,
data: {name, pwd},
errorMessage: '参数不能为空'
})
}, 5000);
})
app.listen(8088, () => {
console.log('server is listening 8088');
})
早期切换页签时可以将source.cancel()放在useEffect返回函数里面执行,当页签下组件销毁时就取消请求
来看看axios是如何实现请求中断的,大致原理是从外部操作promise流触发then回调中断请求
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
var resolvePromise;
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
executor(function cancel(message) {
if (token.reason) {
// Cancellation has already been requested
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
});
}
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c;
});
return {
token: token,
cancel: cancel
};
};
c指cancel函数,当执行source.cancel()时从外部去操作CancelToken的私有属性resolvePromise,也就是resolve函数。
详细流程图如下:
2、fetch
fetch直接使用AbortController来中断请求,详细如下:
首先安装abort-controller库,该库实现了web abort-controller。
yarn add abort-controller -S
import React, { useEffect } from 'react';
import Controller from 'abort-controller';
const AbortController = () => {
const abortController = new Controller();
useEffect(() => {
fetch('http://127.0.0.1:8088/getData', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'zs',
pwd: '123456'
}),
signal: abortController.signal
})
}, []);
const abort = () => {
abortController.abort()
}
return (
<>
<div>this is a abortController page.</div>
<div><button onClick={abort}>取消请求</button></div>
</>
)
}
export default AbortController;
3、$.ajax
$.ajax内部已经实现了abort功能。
ajax(settings?: JQuery.AjaxSettings): JQuery.jqXHR;
interface jqXHR<TResolve = any> extends Promise3<TResolve, jqXHR<TResolve>, never,
Ajax.SuccessTextStatus, Ajax.ErrorTextStatus, never,
jqXHR<TResolve>, string, never>,
Pick<XMLHttpRequest, 'abort' | 'getAllResponseHeaders' | 'getResponseHeader' | 'overrideMimeType' | 'readyState' | 'responseText' |
'setRequestHeader' | 'status' | 'statusText'>,
Partial<Pick<XMLHttpRequest, 'responseXML'>> {
responseJSON?: any;
// 中断请求
abort(statusText?: string): void;
state(): 'pending' | 'resolved' | 'rejected';
statusCode(map: Ajax.StatusCodeCallbacks<any>): void;
}
具体例子:
import React, { useEffect } from 'react';
import $ from 'jquery';
const AbortController = () => {
var abortController: JQuery.jqXHR<any> | null = null;
useEffect(() => {
abortController = $.ajax({
url: 'http://127.0.0.1:8088/getData',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
name: 'zs',
pwd: '123456'
}),
success: function(res) {
console.log(res)
}
})
}, []);
const abort = () => {
abortController?.abort()
}
return (
<>
<div>this is a abortController page.</div>
<div><button onClick={abort}>取消请求</button></div>
</>
)
}
export default AbortController;
推荐阅读
alicdn边缘节点不稳定导致页面崩溃问题
某工作日,线上某用户向客服专员反馈没法正常访问“查看报价页面”,页面内容没有呈现。客服专员收到反馈后,将问题转交给SRE处理。很奇怪的是,SRE访问生产环境“查看报价页面”显示正常,为了进一步分析定位问题,S...
记得要微笑阅读 739
再也不学AJAX了!(三)跨域获取资源 ① - 同源策略
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第四篇,最近更新于 2023 年 1...
libinfs赞 19阅读 4k评论 4
再也不学 AJAX 了!(一)AJAX 概述
跨域获取数据:介绍了与「跨域发送 AJAX 请求」相关的一些内容:例如「同源策略」与四种跨域请求资源的方式:JSONP,CORS,postMessage 和 WebSocket;
libinfs赞 19阅读 3.9k评论 6
再也不学AJAX了!(二)使用AJAX ② Fetch API
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第三篇,最近更新于 2023 年 1...
libinfs赞 2阅读 621
Ajax实现搜索联想 搜索关键词提醒 无刷新搜索
通过javascript监听搜索框的内容,调用后端即可。(1)javascript监听搜索框的内容(2)把搜索框的关键词传给后端进行搜索(3)搜索到结果,遍历到页面
TANKING赞 1阅读 4.4k
如何优雅地封装 axios
如何优雅地封装 axios工作中接手他人的项目,看到一些 axios 封装很是复杂,难用,现在来总结一下 axios 封装 xhr 的问题。在 vue 项目中使用,希望达到下面的效果:引用方便,在组件中,通过 this.$http[method]...
JackZhouMine赞 3阅读 708
vue页面消毁时,取消axios当面所有请求
取消axios请求,需要了解axios里的 cancelToken 属性 {代码...} 首页定义一个数组进行储存每个请求的cancelToken, 可以储存到Vue对象、vuex、window等,在跳转路由时取消请求即可;路由处理
Max迪丶先生赞 1阅读 3.4k
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。