Closed francecil closed 4 years ago
将超时任务 setTimeout 包装成一个 promise , fetch 自身也是一个 promise
利用 Promise.race
的特性 -- "迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝" 解决
function mFetch (url, options, timeout) {
let genTimeoutPromise = (timeout) => new Promise((resolve, reject) => {
setTimeout(reject, timeout)
})
return Promise.race([genTimeoutPromise(timeout), fetch(url, options)])
}
在控制台中测试一下, network 调至 Slow 3G
注意有跨域限制,需要在 baidu 页面的控制台输入测试
mFetch("https://www.baidu.com/", {}, 1000).then((res) => { console.log(res) }).catch(e => { console.log("e:", e) })
可以看到结果输出了
e: undefined
对错误做个包装
reject(new Response("timeout", { status: 504, statusText: "timeout " }))
上述做法,超时后不会处理响应,但是请求还是会继续完成的。
这里需要加个中断功能。
利用 FetchController 实现
function mFetch (url, options, timeout) {
let controller = new AbortController();
let signal = controller.signal;
let genTimeoutPromise = (timeout) => new Promise((resolve, reject) => {
setTimeout(() => {
controller.abort();
reject(new Response("timeout", { status: 504, statusText: "timeout " }))
}, timeout)
})
return Promise.race([genTimeoutPromise(timeout), fetch(url, { ...options, signal })])
}
mFetch("https://www.baidu.com/", {}, 1000).then((res) => {
console.log(res)
}).catch(e => {
console.log("e:", e)
})
通过 network 面板可以看到超时时请求 cancel 了
到达超时时间 fetch 还没有返回响应,则中断请求并 reject promise
提示:需要用到
Promise.race
和AbortController