fetch
使用AbortController在第二个参数中传入signal属性
const control = new AbortController()
const signal = control.signal
fetch('https://juejin.cn/post/7026947170683076621', { signal }).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
setTimeout(() => {
control.abort() // DOMException: The user aborted a request.
}, 50);
axios
使用axios.CancelToken
// http.js 一般都会封装一个http.js文件做一些逻辑处理
// 响应拦截
httpInstance.interceptors.response.use(response => {}, error => {
if(axios.isCancel(error)) {
return Promise.reject(error);
} else {
...
}
})
// axios实例上post方法
httpInstance.post(url, payload, _config)
// *.vue中使用
import api from './api'
import axios from 'axios'
const CancelToken = axios.CancelToken
const source = CancelToken.source()
api.sendRequest(url, query, { cancelToken: source.token })
.then(res => {})
.catch(err => {
console.log(err) // Cancel {message: "user Canceled Token"}
})
setTimeout(() => {
source.cancel('user Canceled Token')
}, 50);
xhr
const xhr = new XMLHttpRequest()
xhr.open('GET', 'https://...', true)
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
...
}
}
xhr.send();
// 调用abort方法取消即可
xhr.abort();
如何从外部退出一组异步任务,并且中断所有还未返回的请求
// 但是感觉非常不优雅,有没有大佬可以帮忙改一下/(ㄒoㄒ)/~~
class CreatAsyncJob {
constructor(taskArr) {
this.taskArr = taskArr
this.responseArr = []
this.abortFlag = false
}
async request() {
for(let t of this.taskArr) {
if(this.abortFlag) {
// this.taskArr === s
// abort放在这里不会取消已发送的请求
// 因为在第一次请求响应时间小于1000ms,第二次时候已经运行到 this.responseArr.push(await t.task()) 做等待了,允许到这里的时候是第三次了
// this.taskArr.forEach(i => i.control.abort()) -->> 这条语句可能不起效
return
}
this.responseArr.push(await t.task())
}
}
abort() {
this.abortFlag = true
}
}
function fetchJob(control) {
return fetch('https://juejin.cn/post/7026947170683076621', { signal: control.signal })
}
const s = new Array(5).fill(null).map((item, idx, arr) => {
const control = new AbortController()
return {
control,
task: () => fetchJob(control)
}
})
const jobs = new CreatAsyncJob(s)
jobs.request()
setTimeout(() => {
jobs.abort()
// abort放在这里就能取消已发送的请求
s.forEach(i => i.control.abort())
console.log(jobs.responseArr); // length: 1
}, 1000);