有一个新的API用于从JavaScript发出请求:fetch()。是否有任何内置机制来取消这些飞行中的请求?
当前回答
正如@spro所说,目前还没有合适的解决方案。
但是,如果您有一个正在运行的响应,并且正在使用ReadableStream,您可以关闭流来取消请求。
fetch('http://example.com').then((res) => {
const reader = res.body.getReader();
/*
* Your code for reading streams goes here
*/
// To abort/cancel HTTP request...
reader.cancel();
});
其他回答
这在浏览器和nodejs Live浏览器演示中工作
const cpFetch= require('cp-fetch');
const url= 'https://run.mocky.io/v3/753aa609-65ae-4109-8f83-9cfe365290f0?mocky-delay=3s';
const chain = cpFetch(url, {timeout: 10000})
.then(response => response.json())
.then(data => console.log(`Done: `, data), err => console.log(`Error: `, err))
setTimeout(()=> chain.cancel(), 1000); // abort the request after 1000ms
正如@spro所说,目前还没有合适的解决方案。
但是,如果您有一个正在运行的响应,并且正在使用ReadableStream,您可以关闭流来取消请求。
fetch('http://example.com').then((res) => {
const reader = res.body.getReader();
/*
* Your code for reading streams goes here
*/
// To abort/cancel HTTP request...
reader.cancel();
});
简单的typescript版本(获取被中止):
export async function fetchWithTimeout(url: RequestInfo, options?: RequestInit, timeout?: number) {
return new Promise<Response>((resolve, reject) => {
const controller = new AbortController();
const signal = controller.signal;
const timeoutId = setTimeout(() => {
console.log('TIMEOUT');
reject('Timeout');
// Cancel fetch in progress
controller.abort();
}, timeout ?? 5 * 1000);
fetch(url, { ...options, signal })
.then((response) => {
clearTimeout(timeoutId);
resolve(response);
})
.catch((e) => reject(e));
});
}
也许你需要一个polyfill(例如IE11):
https://polyfill.io/v3/polyfill.min.js?features=AbortController
从2018年2月起,fetch()可以在Chrome上用下面的代码取消(请阅读使用可读流来启用Firefox支持)。catch()不会抛出任何错误,这是完全采用AbortController之前的临时解决方案。
fetch('YOUR_CUSTOM_URL')
.then(response => {
if (!response.body) {
console.warn("ReadableStream is not yet supported in this browser. See https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream")
return response;
}
// get reference to ReadableStream so we can cancel/abort this fetch request.
const responseReader = response.body.getReader();
startAbortSimulation(responseReader);
// Return a new Response object that implements a custom reader.
return new Response(new ReadableStream(new ReadableStreamConfig(responseReader)));
})
.then(response => response.blob())
.then(data => console.log('Download ended. Bytes downloaded:', data.size))
.catch(error => console.error('Error during fetch()', error))
// Here's an example of how to abort request once fetch() starts
function startAbortSimulation(responseReader) {
// abort fetch() after 50ms
setTimeout(function() {
console.log('aborting fetch()...');
responseReader.cancel()
.then(function() {
console.log('fetch() aborted');
})
},50)
}
// ReadableStream constructor requires custom implementation of start() method
function ReadableStreamConfig(reader) {
return {
start(controller) {
read();
function read() {
reader.read().then(({done,value}) => {
if (done) {
controller.close();
return;
}
controller.enqueue(value);
read();
})
}
}
}
}
让我们polyfill:
if(!AbortController){
class AbortController {
constructor() {
this.aborted = false;
this.signal = this.signal.bind(this);
}
signal(abortFn, scope) {
if (this.aborted) {
abortFn.apply(scope, { name: 'AbortError' });
this.aborted = false;
} else {
this.abortFn = abortFn.bind(scope);
}
}
abort() {
if (this.abortFn) {
this.abortFn({ reason: 'canceled' });
this.aborted = false;
} else {
this.aborted = true;
}
}
}
const originalFetch = window.fetch;
const customFetch = (url, options) => {
const { signal } = options || {};
return new Promise((resolve, reject) => {
if (signal) {
signal(reject, this);
}
originalFetch(url, options)
.then(resolve)
.catch(reject);
});
};
window.fetch = customFetch;
}
请记住,代码没有经过测试!如果你测试过了,发现有些东西不能工作,请告诉我。如果你试图从JavaScript官方库中覆盖'fetch'函数,它可能会给你警告。
推荐文章
- 如何使用Jest测试对象键和值是否相等?
- 将长模板文字行换行为多行,而无需在字符串中创建新行
- 如何在JavaScript中映射/减少/过滤一个集?
- Bower: ENOGIT Git未安装或不在PATH中
- 添加javascript选项选择
- 在Node.js中克隆对象
- 我如何捕捉Ajax查询后错误?
- 为什么在JavaScript的Date构造函数中month参数的范围从0到11 ?
- 使用JavaScript更改URL参数并指定默认值
- 在window.setTimeout()发生之前取消/终止
- 如何删除未定义和空值从一个对象使用lodash?
- 检测当用户滚动到底部的div与jQuery
- 在JavaScript中检查字符串包含另一个子字符串的最快方法?
- 检测视口方向,如果方向是纵向显示警告消息通知用户的指示
- ASP。NET MVC 3 Razor:在head标签中包含JavaScript文件