Skip to content
标签
note
字数
478 字
阅读时间
3 分钟

概述

axios 本质上还是 网络请求+promise回调 的封装

中断网络请求需要建立 dom 元素和 http 请求的绑定,此时可用借助 AbortController 对象

AbortController 对象

构造函数

AbortController.AbortController()

创建一个新的 AbortController 对象实例。

属性

AbortController.signal 只读

返回一个 AbortSignal 对象实例,它可以用来 with/abort 一个 Web(网络)请求。

方法

AbortController.abort()

中止一个尚未完成的 Web(网络)请求。这能够中止 fetch 请求及任何响应体的消费和流

使用示例

js
let controller;
const url = 'video.mp4';

const downloadBtn = document.querySelector('.download');
const abortBtn = document.querySelector('.abort');

downloadBtn.addEventListener('click', fetchVideo);

abortBtn.addEventListener('click', () => {
  if (controller) {
    controller.abort();
    console.log('中止下载');
  }
});

function fetchVideo() {
  controller = new AbortController();
  const signal = controller.signal;
  fetch(url, { signal })
    .then((response) => {
      console.log('下载完成', response);
    })
    .catch((err) => {
      console.error(`下载错误:${err.message}`);
    });
}

Promise对象

代码用例

取消 promise

js
class CancelablePromise<T> {
  
  /**
   * 构造器
   * @param executor Promise中的 executor
   * @param abortSignal AbortController中的signal对象
   * @returns 
   */
  constructor(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void, abortSignal: AbortSignal) {
    
    // 记录reject和resolve方法
    let _reject: any = null;
    let _resolve: any = null;
    let _isExecResolve = false;
    
    // 创建和执行Promise
    const cancelablePromise = new Promise<T>((resolve, reject) => {
      _reject = reject;
      _resolve = (value: T) => {
        _isExecResolve = true;
        resolve(value);
      };
      return executor(_resolve, reject);
    });
    
    // 监听Signal的abourt事件
    abortSignal.addEventListener('abort', () => {
      if (_isExecResolve) {
        return;
      }
      // 抛出错误
      const error = new DOMException('user cancel promise', CancelablePromise.CancelExceptionName );
      _reject( error );
    } );
    return cancelablePromise;
  }
  
  // 取消后抛出的异常名称
  static CancelExceptionName = 'CancelablePromise AbortError';
}


export default CancelablePromise;

取消 axios

可以使用 CancelToken.source 工厂方法创建 cancel token

js
const CancelToken = axios.CancelToken;
const source = CancelToken.source();

axios.get('https://mdn.github.io/dom-examples/abort-api/sintel.mp4', {
  cancelToken: source.token
}).catch(function (thrown) {
  // 判断请求是否已中止
  if (axios.isCancel(thrown)) {
    // 参数 thrown 是自定义的信息
    console.log('Request canceled', thrown.message);
  } else {
    // 处理错误
  }
});

// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');

参考

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

撰写