文章摘要
【前端】面试题挑战 Day2 JavaScript 中如何中止网络请求? - 编程导航 (code-nav.cn) const controller = new AbortController(); const signal = controller.signal; fetch(url, { signal }).then(response = { // Handle the response })…
【前端】面试题挑战 Day2 JavaScript 中如何中止网络请求? - 编程导航 (code-nav.cn) const controller = new AbortController(); const signal = controller.signal; fetch(url, { signal }).then(response = { // Handle the response }).catch(error = { if (error.name === 'AbortError') { console.log('Request was cancelled'); } else { console.log('Request failed:', error); } }); // To abort the request, call the following: controller.abort(); js 给的 api 让我们可以随时中断一个 fetch 请求,那么,如果我想造轮子实现这个功能该怎么做呢? Promise 首先能想到的是用一个 Promise ,来包装 fetch 返回的 promise ,再使用包装的 Promise.reject 方法来实现中断请求 不过函数返回时我使用了 Promise.race 而不直接返回 abortPromise ,原因是因为 fetch 可能返回异常,直接返回包装的 promise 则可能产生无法捕获的异常 以下是示例代码 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); }); 输出: Fetch "./serverConfig.json" has been aborted 代码缺陷也显而易见,这段代码虽然能拦截 fetch 的返回,但是 fetch 占用的网络资源并不会被释放。 也就是说,如果api请求还在 pending 状态,控制台 network 列表仍然能看到 fetch 还在请求状态,占用着io资源。 所以,如果想要 abort 的同时,释放 fetch 占用的资源,单靠 Promise 是不够的。 XMLHttpRequest.abort() 可以使用 XML 代替 fetch ,反正造轮子就是为了绕开 fetch ,封装就完了 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); }); 输出: Fetch "./serverConfig.json" has been aborted 和 fetch 的原生 abort 代码对比,可以看到请求大小为0B,说明请求虽然发出去了,但是浏览器直接断开了连接,并没有选择接收。于是实现了一个简单的 fetchAbort 不过封装程度还不够,剩下的轮子就不造了,了解原理才是本次造轮子的目的。js给的api让我们可以随时中断一个fetch请求,那么,如果我想造轮子实现这个功能该怎么做呢?
Promise
首先能想到的是用一个Promise,来包装fetch返回的promise,再使用包装的Promise.reject方法来实现中断请求
不过函数返回时我使用了Promise.race而不直接返回abortPromise,原因是因为fetch可能返回异常,直接返回包装的promise则可能产生无法捕获的异常
以下是示例代码
输出:
代码缺陷也显而易见,这段代码虽然能拦截fetch的返回,但是fetch占用的网络资源并不会被释放。
也就是说,如果api请求还在pending状态,控制台network列表仍然能看到fetch还在请求状态,占用着io资源。
所以,如果想要abort的同时,释放fetch占用的资源,单靠Promise是不够的。
XMLHttpRequest.abort()
可以使用XML代替fetch,反正造轮子就是为了绕开fetch,封装就完了
输出:
和fetch的原生abort代码对比,可以看到请求大小为0B,说明请求虽然发出去了,但是浏览器直接断开了连接,并没有选择接收。于是实现了一个简单的fetchAbort

不过封装程度还不够,剩下的轮子就不造了,了解原理才是本次造轮子的目的。
本文采用 CC BY-NC-SA 4.0 协议进行授权,如无注明均为原创,转载请注明出处。
标题:[星球打卡] JavaScript 中如何中止网络请求?作者:九仞之行链接:http://dev.styunlen.cn/archives/post-1620.html
还没有评论呢 ~ 快来抢沙发吧 🛋️