代码片段-Promise异步请求超时重连

本文介绍了如何使用Promise与XHR结合,实现异步请求在超时时自动重连的功能。通过监听XHR的超时属性和事件,结合Promise封装一个带超时处理的请求函数,并在类中管理重连的尝试次数和最大次数。

本文不是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();
        });
    };
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值