一、场景
页面请求接口受当前网络的友好程度影响,若迟迟不能请求,应取消相关请求。
二、不同接口交互方式下的超时设置
以下列出了始终前后端的交互方式,其中前三项都是自带了 timeout
参数,设置相应的超时时间即可,但是在使用 fetch
时,超时时间设置不见了。ES6
以后 Promise
出现解决地狱回调的方式:
var promise1 = () => {
return new Promise((resolve, reject) => {});
};
var promise2 = () => {
return new Promise((resolve, reject) => {});
};
Promise.race([promise1, promise2]); // 传入多个Promise对象,等待最快对象完成
Promise.all([promise1, promise2]); // 传入多个Promise 对象,等待所有对象完成
于是可以结合函数 setTimeout
实现 fetch
的超时设置
2.1、XMLHttpRequest
原生接口请求方式
let xhr = new XMLHttpRequest();
xhr.timeout = 3000; // 设置xhr请求的超时时间
xhr.open('post', 'http://172.16.0.92/xxx', true);
xhr.ontimeout = function (e) {
console.log('请求超时:', e);
};
xhr.send();
2.2、Ajax
jQuery 封装的请求方式
$.ajax({
timeout: 3000, // 设置超时时间
});
2.3、axios
它本身是对原生 XHR
的封装
axios({
method: 'post',
url: '/user/12345',
timeout: 3000, // 设置超时时间
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
- 支持
node
,创建http
请求; - 支持
Promise API
; - 客户端防止
CSRF
:每个请求带一个cookie
拿到的key
; - 拦截请求和响应;
- 可取消请求。
2.4、fetch
基于 Promise
的异步处理机制
/**
* @param {String} url 接口地址
* @param {Object} option 配置参数
* @description fetch 请求封装
*/
function fetchHttp(url, option) {
var newOptions = {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json; charset=utf-8',
},
mode: 'cors',
redirect: 'follow',
referrer: 'no-referrer',
method: option.method,
body: option.body,
// ...option,
};
// if ( ['POST', 'PUT', 'DELETE'].includes(option.method)) {
if (option.method === 'POST' || option.method === 'PUT' || option.method === 'DELETE') {
if (!(option.body instanceof FormData)) {
newOptions.body = JSON.stringify(newOptions.body);
}
}
// 添加超时拦截请求
var controller = new AbortController();
var signal = controller.signal;
// 任务1:超时定时任务
var timeoutPromise = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(new Response('timeout', { status: 504, statusText: 'timeout ' }));
controller.abort();
}, timeout);
});
}
// 任务2:接口请求
var requestPromise = () => {
newOptions.signal = signal;
return fetch(url, newOptions)
.then(function (response) {
if (option.method === 'DELETE' || response.status === 204) {
return response.text();
}
return response.json();
})
.then(function (res) {
if (option.callback) option.callback(res);
return res;
})
.catch(function (error) {
console.error('监控接口请求出错:', error);
});
};
// 执行多个任务:等待最快对象完成
Promise.race([timeoutPromise(), requestPromise()])
.then(resp => {
console.log(resp);
})
.catch(error => {
console.log('请求超时:', e);
});
}
Promise.race(iterable)
方法返回一个Promise
,一旦迭代器中的某个Promise
解决或拒绝,返回的Promise
就会解决或拒绝。- 更加底层,提供的API丰富
request, response
; - 语法简单,脱离了
XHR
,基于ES新的Promise
设计。
2.5、 Beacon
接口用于将异步和非阻塞请求发送到服务器。Beacon
请求使用 HTTP
协议中的 POST
方法,请求通常不需要响应。这个请求被保证在,页面的 unload
状态从发起到完成之前被发送。且不会产生请求阻塞,影响页面性能,所以不需要设置超时。更多内容详见 sendBeacon 实现数据上报