本文博客地址:如何取消 Web 请求.
在有些场景下可能需要用到取消请求的操作,比如在同一时刻触发多次请求,只保留最新的请求;比如表单提交中关闭页面等行为,本文加少一些常用的触发 Web 请求的方式如何取消。
AbortControllor
AbortController 接口表示一个控制器对象,该对象允许您在需要时中止一个或多个 Web 请求。
AbortController 分别有一个属性 AbortController.signal 和一个方法 AbortController.abort,他们结合起来可以用来终止 Web 请求。
它的使用过程如下:
首先创建一个 AbortController 对象 controller,然后在调用 fetch 时,传入 controller.signal 作为选项,此时控制器和请求被关联在一起,使用控制器的 controller.abort 方法,即刻终止此请求。
const controller = new AbortController();
function download() {
return fetch(url, { signal: controller.signal });
}
function abort() {
controller.abort();
}
注意,当 controller.abort 被调用时, fetch 返回的 promise 会进入 reject 状态并返回一个名为 AbortError 的 DOMException。
AbortController.signal 搭配 AbortController.abort 还可以用来响应一些取消类的行为:
const controller = new AbortController();
controller.signal.addEventListener('abort', (err) => {
console.log('aborted!');
});
controller.abort();
// 输出
aborted!
注意,AbortControllor 只对浏览器原生的 fetch 生效,在日常开发中经常使用其它的工具如 axios,下一节看一下 axios 怎么取消。
axios 请求取消
axios 提供了 cancelToken 配置项可以用来取消其请求,其使用和 AbortControllor 很相似,看下面的例子:
const cancelToken = axios.CancelToken;
const source = cancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function (thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// handle error
}
});
// cancel the request (the message parameter is optional)
source.cancel();
也可以给 CancelToken 传入一个执行器来执行:
const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
cancel = c;
})
});
// cancel the request
cancel();
都写到这里了,顺便看看 axios 内部是怎么实现取消的:
首先看 cancelToken 相关的代码:
// lib/adapters/xhr.js
if (config.cancelToken) {
// Handle cancellation
config.cancelToken.promise.then(function onCanceled(cancel) {
if (!request) {
return;
}
request.abort();
reject(cancel);
// Clean up request
request = null;
});
}
可以看到当 cancelToken.promise 调用 resolve 时进行了取消,结合它的使用不难猜测 cancelToken.source().cancel 和 传入 CancelToken 的 executor 返回给用户的方法一定用来是 resolve cancelToken.promise 的,接着找相关代码:
// lib/cancel/CancelToken.js
CancelToken.source = function source() {
var cancel;
var token = new CancelToken(function executor(c) {
cancel = c;
});
return {
token: token,
cancel: cancel
};
};
从上面看出 axios 的第一个示例 cancelToken.source 方法就是是调用了 CancelToken 构造器,也就是上面 axios 示例的第二种写法,后面就没必要看了,继续找构造器相关的代码就知道做了什么:
// lib/cancel/CancelToken.js
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);
});
}
很明显可以看出 this.promise 就是 config.cancelToken.promise.then,而 executor 就是 new CancelToken 时传入的方法,最终暴露给外面了 function cancel 这个方法,而这个方法就是用来 config.cancelToken.promise,和前面的猜测一致,不在多说。
同样的,使用同一个 cancelToken 也可以取消多个请求。
中止 Promise
Promise 也可以手动中止,只需要在创建 Promise 时,对外暴露 reject:
let abort;
let p = new Promise((resovle, reject) => {
abort = err => reject(err);
// do sth;
});
abort();
XHR 请求取消
XHR 原生提供了 abort 方法,可以直接取消:
let xhr = new XMLHttpRequest();
xhr.onerror = (err) => console.log(err);
xhr.onabort = () => console.log('aborted!');
xhr.open('get', 'http://baidu.com');
xhr.send();
setTimeout(() => {
xhr.abort();
}, 100);
注意,和其他不同的是,xhr 取消不会触发 error 事件,而是触发 abort 事件。
参考
本文博客地址:如何取消 Web 请求.
在有些场景下可能需要用到取消请求的操作,比如在同一时刻触发多次请求,只保留最新的请求;比如表单提交中关闭页面等行为,本文加少一些常用的触发 Web 请求的方式如何取消。
AbortControllor
AbortController接口表示一个控制器对象,该对象允许您在需要时中止一个或多个 Web 请求。AbortController分别有一个属性AbortController.signal和一个方法AbortController.abort,他们结合起来可以用来终止 Web 请求。它的使用过程如下:
首先创建一个
AbortController对象controller,然后在调用fetch时,传入controller.signal作为选项,此时控制器和请求被关联在一起,使用控制器的controller.abort方法,即刻终止此请求。注意,当 controller.abort 被调用时, fetch 返回的 promise 会进入 reject 状态并返回一个名为 AbortError 的 DOMException。
AbortController.signal搭配AbortController.abort还可以用来响应一些取消类的行为:注意,
AbortControllor只对浏览器原生的fetch生效,在日常开发中经常使用其它的工具如axios,下一节看一下 axios 怎么取消。axios 请求取消
axios提供了cancelToken配置项可以用来取消其请求,其使用和AbortControllor很相似,看下面的例子:也可以给
CancelToken传入一个执行器来执行:都写到这里了,顺便看看 axios 内部是怎么实现取消的:
首先看 cancelToken 相关的代码:
可以看到当
cancelToken.promise调用resolve时进行了取消,结合它的使用不难猜测cancelToken.source().cancel和 传入CancelToken的executor返回给用户的方法一定用来是resolvecancelToken.promise的,接着找相关代码:从上面看出 axios 的第一个示例
cancelToken.source方法就是是调用了CancelToken构造器,也就是上面 axios 示例的第二种写法,后面就没必要看了,继续找构造器相关的代码就知道做了什么:很明显可以看出
this.promise就是config.cancelToken.promise.then,而executor就是new CancelToken时传入的方法,最终暴露给外面了function cancel这个方法,而这个方法就是用来config.cancelToken.promise,和前面的猜测一致,不在多说。同样的,使用同一个 cancelToken 也可以取消多个请求。
中止 Promise
Promise也可以手动中止,只需要在创建Promise时,对外暴露reject:XHR 请求取消
XHR 原生提供了 abort 方法,可以直接取消:
注意,和其他不同的是,xhr 取消不会触发
error事件,而是触发abort事件。参考