axios/fetch/XMLHttpRequest怎么取消请求

2,292 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

在项目里经常有取消请求的要求,比如超时30秒后取消请求,跳转新页面时取消上个页面的请求,用户手动取消请求等功能,这些场景都需要取消请求。下面来看看axios/fetch/XMLHttpRequest发送请求,如何取消请求。

axios

在axios中想要取消请求,主要有两种方式,一种是使用 CancelToken.source()工厂函数,一种是使用CancelToken构造函数,两种方式都能够取消请求,一个可用来取消多个请求,一个可以取消单独某个请求。

下面,我们使用CancelToken.source工厂函数来取消请求

相同的cancelToken可以同时取消掉多个请求

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

axios.get('/user/12345', {
  cancelToken: source.token
}).then((data) => console.log(data))
  .catch((error) => {
    // 判断是否为手动取消
    if (axios.isCancel(thrown)) {
      console.log('请求被手动取消: ', error.message);
    } else {
      // 处理其他请求错误
    }
	});

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

// 手动取消请求,参数为可选。(GET - /user/12345 和 POST - /user/12345将被取消请求)
source.cancel('用户手动取消请求');

通过CancelToken构造函数来创建cancelToken

使用CancelToken构造函数可以为每个请求生成单独的cancelToken,用来取消某个单独的请求

const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken((c) => {
    // CancelToken参数为一个回调函数,将cancelToken在函数返回
    cancel = c;
  })
}).then((data) => console.log(data))
  .catch((error) => {
    // 判断是否为手动取消
    if (axios.isCancel(thrown)) {
      console.log('请求被手动取消: ', error.message);
    } else {
      // 处理其他请求错误
    }
	});

// 取消请求
cancel();

fetch

在fetch请求中,需要使用创建一个新的AbortController对象,来取消请求,这个对象中有一个signal属性,将signal传入fetch请求的配置中,然后我们使用AbortControllerabort方法可取消此次请求。

const controller = new AbortController();
const { signal } = controller;

fetch("/user/12345", { signal }).then(response => {
    console.log('请求成功');
}).catch(err => {
  if(err.name === "AbortError") {
		// 请求被手动取消
	} else {
    // 处理错误
  }
});

setTimeout(() => {
  // 手动取消请求
  controller.abort();
}, 1000)

XMLHttpRequest

用XMLHttpRequest发出请求,使用abort()会中止请求,readyState会变为XMLHttpRequest.UNSENT,并且status状态码会变成为0

const xhr = new XMLHttpRequest(),
    method = "GET",
    url = "/user/12345";

xhr.open(method, url, true);
xhr.onreadystatechange = function () {
  if(xhr.readyState === XMLHttpRequest.UNSENT) {
    if (status === 0) {
			// 请求被取消
    }
  } else if(xhr.readyState === XMLHttpRequest.DONE) {
    var status = xhr.status;
    if (status === 0 || (status >= 200 && status < 400)) {
      // 请求成功
      console.log(xhr.responseText);
    } else {
      // 处理错误
    }
  } else if 
};
xhr.send();

setTimeout(() => {
  // 手动取消请求
  xhr.abort();
}, 1000)

总结

无论是通过axios/fetch/XMLHttpRequest哪种方式发送请求,取消方法都大体类似,都是去调用abort()方法,然后在错误的回调中判断是否为手动取消请求。