有一个新的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();
});
其他回答
https://developers.google.com/web/updates/2017/09/abortable-fetch
https://dom.spec.whatwg.org/#aborting-ongoing-activities
// setup AbortController
const controller = new AbortController();
// signal to pass to fetch
const signal = controller.signal;
// fetch as usual
fetch(url, { signal }).then(response => {
...
}).catch(e => {
// catch the abort if you like
if (e.name === 'AbortError') {
...
}
});
// when you want to abort
controller.abort();
支持edge 16(2017-10-17)、firefox 57(2017-11-14)、桌面safari 11.1(2018-03-29)、ios safari 11.4(2018-03-29)、chrome 67(2018-05-29)及更高版本。
在旧的浏览器上,你可以使用github的whatwg-fetch polyfill和AbortController polyfill。你也可以检测旧的浏览器,并有条件地使用填充:
import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
import {fetch} from 'whatwg-fetch'
// use native browser implementation if it supports aborting
const abortableFetch = ('signal' in new Request('')) ? window.fetch : fetch
TL / diana:
fetch现在支持信号参数截至2017年9月20日,但不是 目前所有浏览器似乎都支持这个功能。
2020年更新:大多数主流浏览器(Edge、Firefox、Chrome、Safari、Opera和其他一些浏览器)都支持该功能,该功能已成为DOM生活标准的一部分。(截至2020年3月5日)
这是我们很快就会看到的变化,因此您应该能够通过使用AbortControllers AbortSignal来取消请求。
长版本
如何:
它的工作方式是这样的:
步骤1:创建AbortController(目前我只使用它)
const controller = new AbortController()
步骤2:你像这样得到AbortControllers信号:
Const signal = controller.signal
第三步:像这样传递获取的信号:
fetch(urlToFetch, {
method: 'get',
signal: signal, // <------ This is our AbortSignal
})
第四步:需要的时候就放弃:
controller.abort();
下面是它如何工作的一个例子(适用于Firefox 57+):
<script> // Create an instance. const controller = new AbortController() const signal = controller.signal /* // Register a listenr. signal.addEventListener("abort", () => { console.log("aborted!") }) */ function beginFetching() { console.log('Now fetching'); var urlToFetch = "https://httpbin.org/delay/3"; fetch(urlToFetch, { method: 'get', signal: signal, }) .then(function(response) { console.log(`Fetch complete. (Not aborted)`); }).catch(function(err) { console.error(` Err: ${err}`); }); } function abortFetching() { console.log('Now aborting'); // Abort. controller.abort() } </script> <h1>Example of fetch abort</h1> <hr> <button onclick="beginFetching();"> Begin </button> <button onclick="abortFetching();"> Abort </button>
来源:
AbortController的最终版本已经添加到DOM规范中 取回规范对应的PR现在被合并了。 跟踪AbortController实现的浏览器错误可以在这里找到:Firefox: #1378342, Chromium: #750599, WebKit: #174980, Edge: #13009916。
这在浏览器和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
让我们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'函数,它可能会给你警告。
正如@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();
});
推荐文章
- jQuery:执行同步AJAX请求
- 如何禁用文本选择使用jQuery?
- 如何停止事件冒泡复选框点击
- 向对象数组添加属性
- 如何在Redux应用程序中动态加载代码分割的减速器?
- Angular 2+和debounce
- 检测涡旋方向
- 在react native中隐藏/显示组件
- 在网页上用鼠标模拟震颤(例如帕金森病)?
- console.log()和console.debug()的区别?
- 如何删除和清除所有的本地存储数据
- 如何从给定的html字符串中删除前导和尾随空白?
- 如何为KnockoutJS调试模板绑定错误?
- 将一个二进制的NodeJS Buffer转换为JavaScript的ArrayBuffer
- 检测浏览器标签是否有焦点