当前位置:   article > 正文

axios取消请求cancelToken和AbortController_axios.canceltoken

axios.canceltoken

目录

本质:观察订阅+xhr.abort()

就绪状态readyState:0

状态码status:0

cancelToken

源码

CancelToken

(un)subscribe

 source

示例

A.axios.canceltoken

B.source对象创建canceltoken

AbortController接口:(控制器对象)

源码

替换原因

保持与fetch一样的调用方式,让开发者更好上手

CancelToken存在内存泄露隐患【切片上传长时间没有中断】

示例

axios

fetch

本质:观察订阅+xhr.abort()

就绪状态readyState:0

  • 取值范围是 0 到 4,分别表示不同的状态:
    • 0: 请求未初始化(open 方法还未调用)。
    • 1: 服务器连接已建立(open 方法已经调用)。
    • 2: 请求已接收(send 方法已经调用,并且头部和状态已经可获得)。
    • 3: 请求处理中(响应体正在接收)。
    • 4: 请求已完成,且响应已就绪。

状态码status:0

  1. // 创建AbortController实例且存放到controller上
  2. // 注意这里每次请求都会创建一个新的AbortController实例,
  3. //是因为AbortController实例调用abort后
  4. //AbortController实例的状态signal就为aborted不能更改
  5. controller.current = new AbortController();
  6. const xhr = new XMLHttpRequest();
  7. xhr.open("get", "https://mdn.github.io/dom-examples/abort-api/sintel.mp4");
  8. xhr.onreadystatechange = () => {
  9. if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
  10. setMessage("下载成功");
  11. setLoading(false);
  12. }
  13. };
  14. // 监听AbortController实例的abort事件,当AbortController实例调用abort方法时,就会触发该事件执行回调
  15. controller.current.signal.addEventListener("abort", () => {
  16. setMessage("下载中止");
  17. setLoading(false);
  18. xhr.abort();
  19. });
  20. xhr.send();
  21. // 调用AbortController实例的abort方法,从而触发上面注册在abort事件的回调的执行
  22. const abortDownload = () => {
  23. controller.current.abort();
  24. };

cancelToken

源码

CancelToken

  1. function CancelToken(executor) {
  2. if (typeof executor !== "function") {
  3. throw new TypeError("executor must be a function.");
  4. }
  5. var resolvePromise;
  6. this.promise = new Promise(function promiseExecutor(resolve) {
  7. resolvePromise = resolve;
  8. });
  9. var token = this;
  10. this.promise.then(function (cancel) {
  11. if (!token._listeners) return;
  12. var i;
  13. var l = token._listeners.length;
  14. // 遍历执行所有注册的监听器
  15. for (i = 0; i < l; i++) {
  16. token._listeners[i](cancel);
  17. }
  18. // 清空监听器数组
  19. token._listeners = null;
  20. });
  21. // source.cancel指向此处的cancel函数
  22. //在取消时调用 resolvePromise 函数
  23. executor(function cancel(message) {
  24. // token.reason有值代表cancel已被执行,CancelToken是一个一次性的Subject,notify一次后即失效
  25. if (token.reason) {
  26. return;
  27. }
  28. token.reason = new CanceledError(message);
  29. // resolvePromise执行时,会执行上面this.promise.then中传入的回调函数。从而把listeners全执行
  30. resolvePromise(token.reason);
  31. });
  32. }
(un)subscribe

  1. 请求前subscribe注册onCancel函数
  2. 请求后unsubscribe注销onCancel函数
  1. CancelToken.prototype.subscribe = function subscribe(listener) {
  2. // 如果CancelToken实例已经执行cancel,直接执行该回调函数
  3. if (this.reason) {
  4. listener(this.reason);
  5. return;
  6. }
  7. // 如果CancelToken实例还没执行cancel,则把回调函数放进_listeners里
  8. if (this._listeners) {
  9. this._listeners.push(listener);
  10. } else {
  11. this._listeners = [listener];
  12. }
  13. };
  14. // 把回调函数从_listeners中移除
  15. CancelToken.prototype.unsubscribe = function unsubscribe(listener) {
  16. if (!this._listeners) {
  17. return;
  18. }
  19. var index = this._listeners.indexOf(listener);
  20. if (index !== -1) {
  21. this._listeners.splice(index, 1);
  22. }
  23. };
 source
  1. CancelToken.source = function source() {
  2. var cancel;
  3. var token = new CancelToken(function executor(c) {
  4. cancel = c;
  5. });
  6. return {
  7. token: token,
  8. cancel: cancel,
  9. };
  10. };

示例

A.axios.canceltoken

  1. //初始化
  2. let cancel = null;
  3. //请求
  4. if(cancel != null) cancel() //如果上一次的请求还在继续,则取消
  5. axios({
  6. method:"get",
  7. url:"http://localhost:3000/test.php",
  8. cancelToken:new axios.CancelToken(function(c){
  9. cancel = c
  10. })
  11. }).then(response=>{
  12. //处理响应数据
  13. cancel = null
  14. }).catch(reason=>{
  15. //错误处理
  16. })
  17. }

B.source对象创建canceltoken

  1. let source = axios.CancelToken.source();
  2. // 判断上一次的请求是否还在继续,如果还在继续,则取消上一次的请求
  3. if(source.token._listeners!=undefined )
  4. {
  5. source.cancel("取消请求")
  6. source = axios.CancelToken.source()
  7. }
  8. axios.get('http://localhost:3000/front-end/axios/response.php',{
  9. cancelToken:source.token
  10. }).then(response=>{
  11. // 处理响应
  12. }).catch(reason=>{
  13. if(axios.isCancel(reason)){
  14. console.log("取消请求",reason)
  15. }else{
  16. //错误处理
  17. }
  18. })
  19. }

AbortController接口:(控制器对象)

2021 年 10 月推出的AxiosV0.22.0版本中把CancelToken打上 声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】

推荐阅读
相关标签