本文不是Promise超时重试,而是XHR异步请求与Promise结合后的自动重连
- 如何发现请求超时?依靠XHR自身就有的超时属性和事件
var xhr = new XMLHttpRequest();
xhr.open('GET', '/server', true);
// 1. timeout属性:超时时间,单位是毫秒
xhr.timeout = 2000;
xhr.onload = function () { /* onload事件请求完成 */ };
// 2. ontimeout事件回调
xhr.ontimeout = function (e) { /* 请求超时处理函数 */ };
xhr.send(null);
注:onload可被认为是onreadystatechange中确认到readyState == 4,但这只能说明服务器无异常 却不保证返回数据,因此status in [200, 300)仍然需要在回调函数内部进行判断
- 那么用Promise封装带超时处理的XHR函数代码示例如下:
const newRequest = (url, timeout) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.timeout = timeout;
xhr.ontimeout = () => { reject('超时'); };
xhr.onerror = () => { reject('错误'); };
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
}
};
xhr.open("GET", url, true);
xhr.send();
});
};
- 将尝试次数与最大次数存入类的状态,使用上面封装的请求函数加入,可重连的请求类可以像这样使用:
// 实例化时把最大请求次数存入类状态
const rr = new RetriableRequest(maxRetryTime = 10);
// 发请求时 设置请求超时时间
rr.request("http://a.com/api", timeout = 5000);
类定义代码如下:
class RetriableRequest {
constructor(maxRetryTime = 0) {
this.maxRetryTime = maxRetryTime;
this.retryTime = 0;
}
// 调度逻辑:
request(url, timeout = Infinity) {
this.newRequest(url, timeout)
.then(res => {
Promise.resolve(res);
})
.catch(err => {
console.log(err, "即将重连");
if (this.retryTime < this.maxRetryTime) {
this.request(url, timeout);
this.retryTime++;
} else {
Promise.reject(err);
}
});
}
// 前文封装的promise-xhr请求
newRequest(url, timeout) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.timeout = timeout;
xhr.ontimeout = () => { reject('超时'); };
xhr.onerror = () => { reject('错误'); };
xhr.onload = () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(xhr.response);
}
};
xhr.open("GET", url, true);
xhr.send();
});
};
}
本文介绍了如何使用Promise与XHR结合,实现异步请求在超时时自动重连的功能。通过监听XHR的超时属性和事件,结合Promise封装一个带超时处理的请求函数,并在类中管理重连的尝试次数和最大次数。
983

被折叠的 条评论
为什么被折叠?



