fetch 设置请求超时
在使用 js 自带的 fecth 做网络请求时,没有提供例如$ajax 的超时选项,所以需要自己实现
多个fetch请求在网络不稳定的情况下,会占用大量内存,因为当网速很慢的情况下,fetch会一直等待,直到收到响应
原理
使用Promise.race
, Promise.race 的作用是哪个 Promise 先返回结果则最终输出这个 Promise 的返回值
// 超时函数
const timeoutAction = timer => {
return new Promise(reslove => {
setTimeout(() => {
// 实例化超时响应json数据
const response = new Response(
JSON.stringify({
code: 1,
msg: `timeout ${timer}s`
})
);
return reslove(response);
}, timer * 1000);
});
};
const url = "/data.json"; // 请求的url
// 执行,超时控制在0秒,让它永远超时,方便观察
Promise.race([timeoutAction(0), fetch(url)])
.then(res => {
return res.json();
})
.then(res => {
if (res.code !== 0) {
return alert(res.msg);
} else {
return console.log(res);
}
});
最终实现
上述代码只是让浏览器直到已经超时,而实际上的fetch请求还在继续,所以要多做一步操作, 在超时的时候手动终止fetch请求
AbortController 用于手动终止一个或多个DOM请求,通过该对象的AbortSignal注入的Fetch的请求中。所以需要完美实现timeout功能加上这个就对了
let controller = new AbortController();
let signal = controller.signal;
// 超时函数
const timeoutAction = timer => {
return new Promise(reslove => {
setTimeout(() => {
// 实例化超时响应json数据
const response = new Response(
JSON.stringify({
code: 1,
msg: `timeout ${timer}s`
})
);
reslove(response);
controller.abort(); // 发送终止信号
}, timer * 1000);
});
};
const url = "/data.json"; // 请求的url
// 执行,超时控制在0秒,让它永远超时,方便观察
Promise.race([
timeoutAction(0),
fetch(url, {
signal: signal //设置信号
})
])
.then(res => {
return res.json();
})
.then(res => {
if (res.code !== 0) {
return alert(res.msg);
} else {
return console.log(res);
}
});
目的验证
当看到浏览器异步请求的状态值为canceled时,说明超时拦截成功
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。