本文发布于 2023-02-21, 最后更新于 1281 天前,其中的信息可能已经有所发展或是发生改变。

文章摘要

【前端】面试题挑战 Day2 JavaScript 中如何中止网络请求? - 编程导航 (code-nav.cn) const controller = new AbortController(); const signal = controller.signal; fetch(url, { signal }).then(response = { // Handle the response })…

js给的api让我们可以随时中断一个fetch请求,那么,如果我想造轮子实现这个功能该怎么做呢?

Promise

以下是示例代码

dns (Auto identified)
const fetchAbort = (url: string) => { let res, abort; const abortPromise = new Promise<Response>((resolve, reject) => { res = resolve; abort = reject.bind(this, `Fetch "${url}" has been aborted`); }); return { response: Promise.race([fetch(url).then(ret => res(ret)), abortPromise]), abort }; }; const { response, abort } = fetchAbort("./serverConfig.json"); abort(); // abort后,response的promise链将catch到fetch abort消息 // 而不会返回fetch返回的消息 response .then(ret => ret.text()) .then(txt => console.log(txt)) .catch(err => { console.log(err); });

输出:

text
Fetch "./serverConfig.json" has been aborted

代码缺陷也显而易见,这段代码虽然能拦截fetch的返回,但是fetch占用的网络资源并不会被释放。

也就是说,如果api请求还在pending状态,控制台network列表仍然能看到fetch还在请求状态,占用着io资源。

所以,如果想要abort的同时,释放fetch占用的资源,单靠Promise是不够的。

XMLHttpRequest.abort()

可以使用XML代替fetch,反正造轮子就是为了绕开fetch,封装就完了

dns (Auto identified)
const fetchAbort = (url: string) => { let res, abort, xhr; const xhrPromise = new Promise((resolve, reject) => { xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (this.status == 200) { return resolve(this.response); } return reject({ xhr: this, msg: "Error", status: this.status, statusText: this.statusText }); } }; xhr.open("Get", url); xhr.send(); }); const abortPromise = new Promise((resolve, reject) => { res = resolve; abort = () => { xhr.abort(); return reject(`Fetch "${url}" has been aborted`); }; }); return { response: Promise.race([xhrPromise.then(ret => res(ret)), abortPromise]), abort }; }; const { response, abort } = fetchAbort("./serverConfig.json"); abort(); response .then(ret => console.log(ret)) .catch(err => { console.log(err); });

输出:

text
Fetch "./serverConfig.json" has been aborted

fetch的原生abort代码对比,可以看到请求大小为0B,说明请求虽然发出去了,但是浏览器直接断开了连接,并没有选择接收。于是实现了一个简单的fetchAbort

不过封装程度还不够,剩下的轮子就不造了,了解原理才是本次造轮子的目的。

九仞之行

严于律己,宽以待人,深自警省,讷言敏行

订阅
💬 评论 (0)

还没有评论呢 ~ 快来抢沙发吧 🛋️

编辑器加载中…