前端如何取消一个 Fetch API 请求 All In One
前端如何取消一个 Fetch API 请求 All In One
cancel http request
AbortController
signal
const controller = new AbortController();
controller;
// AbortController {signal: AbortSignal}signal: AbortSignalaborted: falseonabort: nullreason: undefined[[Prototype]]: AbortSignal[[Prototype]]: AbortController
controller.abort();
// undefined
controller;
// AbortController {signal: AbortSignal}signal: AbortSignal {aborted: true, reason: DOMException: signal is aborted without reason at <anonymous>:1:12, onabort: null} [[Prototype]]: AbortController
https://developer.mozilla.org/en-US/docs/Web/API/AbortController
demos
使用 AbortController API 实现 debounce 防抖效果 ✅
// 外部变量
let controller;
const url = "video.mp4";
// const url = "https://mdn.github.io/dom-examples/abort-api/sintel.mp4";
const downloadBtn = document.querySelector('.download');
const abortBtn = document.querySelector('.abort');
abortBtn.addEventListener('click', function() {
if (controller) {
controller.abort();
console.log('Download aborted');
}
});
downloadBtn.addEventListener('click', fetchVideo);
function fetchVideo() {
// 外部变量赋值
controller = new AbortController();
const signal = controller.signal;
fetch(url, { signal })
.then(function(res) {
console.log('Download complete', res.text());
})
.catch(function(err) {
console.log('Download error: ' + err.message);
});
}
https://mdn.github.io/dom-examples/abort-api/
demos
let controller;
function fetchVideo() {
controller = new AbortController();
const signal = controller.signal;
fetch(url, { signal })
.then(response => {
console.log('Download complete', response);
})
.catch(err => {
console.log('Download error: ' + err.message);
});
}
(🐞 反爬虫测试!打击盗版⚠️)如果你看到这个信息, 说明这是一篇剽窃的文章,请访问 https://www.cnblogs.com/xgqfrms/ 查看原创文章!
abortable fetch
https://developers.google.com/web/updates/2017/09/abortable-fetch
demo
https://fetch-svg-abort.glitch.me/
blogs
https://www.carlrippon.com/cancelling-fetch-in-React-and-typescript/
https://segmentfault.com/a/1190000039841110
https://gist.github.com/carlrip/4f01187cef825f3b7d8cc953ab876b8b
// TS & React
import React from "react";
type Character = {
name: string;
};
interface PromiseWithCancel<T> extends Promise<T> {
cancel: () => void;
}
function getCharacter(id: number) {
const controller = new AbortController();
const signal = controller.signal;
const promise = new Promise(async (resolve) => {
try {
const response = await fetch("https://swapi.dev/api/people/" + id, {
method: "get",
signal,
});
const data = await response.json();
assertIsCharacter(data);
resolve(data);
} catch (ex: unknown) {
if (isAbortError(ex)) {
console.log(ex.message);
}
}
});
(promise as PromiseWithCancel<Character>).cancel = () => controller.abort();
return promise as PromiseWithCancel<Character>;
}
function assertIsCharacter(data: any): asserts data is Character {
if (!("name" in data)) {
throw new Error("Not character");
}
}
function isAbortError(error: any): error is DOMException {
if (error && error.name === "AbortError") {
return true;
}
return false;
}
export function App() {
const [status, setStatus] = React.useState<
"loading" | "loaded" | "cancelled"
>("loading");
const [data, setData] = React.useState<Character | undefined>(undefined);
const [query, setQuery] = React.useState<
PromiseWithCancel<Character> | undefined
>(undefined);
React.useEffect(() => {
const q = getCharacter(1);
setQuery(q);
q.then((character) => {
setData(character);
setStatus("loaded");
});
}, []);
if (status === "loading") {
return (
<div>
<div style={{ margin: "20px 0px 5px" }}>loading ...</div>
<button
onClick={() => {
query?.cancel();
setStatus("cancelled");
}}
>
Cancel
</button>
</div>
);
}
if (status === "cancelled") {
return <div>Cancelled</div>;
}
return <div>{data && <h3>{data.name}</h3>}</div>;
}
https://davidwalsh.name/cancel-fetch
https://juejin.cn/post/6844904113130438663
refs
©xgqfrms 2012-2021
www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!
原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!
本文首发于博客园,作者:xgqfrms,原文链接:https://www.cnblogs.com/xgqfrms/p/16028578.html
未经授权禁止转载,违者必究!