# 取消请求

发出去的请求如何取消?下面进行总结。

# AbortController

AbortController 接口表示一个控制器对象,允许你根据需要中止一个或多个 Web 请求。

  • AbortController()AbortController()构造函数创建一个新的 AbortController 对象实例
  • signalsignal 属性返回一个 AbortSignal 对象实例,它可以用来 with/about 一个Web(网络)请求
  • abort():终止一个尚未完成的Web(网络)请求,它能够终止 fetch 请求,任何响应Body的消费者和流

MDN上的示例如下:

const controller = new AbortController(); // 创建控制器
let signal = controller.signal; // AbortSignal 对象的引用

console.log(signal.aborted) // false

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

downloadBtn.addEventListener('click', fetchVideo);

abortBtn.addEventListener('click', function() {
  controller.abort(); // 当 abort() 被调用时,这个 fetch() promise 将 reject 一个名为 AbortError 的 DOMException。
  console.log(signal.aborted) // true
});

function fetchVideo() {
  //...
  fetch(url, {signal}).then(function(response) { // 传递AbortSignal
    //...
  }).catch(function(e) { //  AbortError 的 DOMException
    reports.textContent = 'Download error: ' + e.message;
  })
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

先使用 AbortController() 构造函数创建一个控制器,然后使用 AbortController.signal 属性获取其关联 AbortSignal 对象的引用。

其中,AbortSignal接口表示一个信号对象,它允许您通过 AbortController 对象与DOM请求(如Fetch)进行通信并在需要时将其中止。

AbortSignal包括两个属性:

AbortSignal.aborted(只读):表示与之通信的请求是否被终止(true)或未终止(false)。 AbortSignal.onabort:当 abort 事件触发时,即当信号正在与之通信的DOM请求被中止时调用。

也就是说,上述示例中,当没有中止请求时,变量signal里的aborted属性为false,中止后,属性为true

fetch request 初始化时,我们把 AbortSignal 作为一个选项传递到到请求对象(上述示例的第二个参数)。

这将 signalcontroller 与这个 fetch request 相关联,然后允许我们通过调用 AbortController.abort() 中止请求。

# axios中断请求

1、通过 CancelToken.source 工厂函数进行取消

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
  }
});

axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token
})

// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

2、通过 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();
1
2
3
4
5
6
7
8
9
10
11
12

3、通过 AbortController 中断请求

const controller = new AbortController();

axios.get('/foo/bar', {
   signal: controller.signal
}).then(function(response) {
   //...
});
// cancel the request
controller.abort()
1
2
3
4
5
6
7
8
9

# 总结

本文总结了取消请求的两种方案,一种是fetch提供的AbortController,另一种是axios提供的取消方案,由于AbortController有兼容性的问题,因此建议使用axios的取消请求。