面试遇到的问题

当场竟然没写出来

let HTTP = {}
// request with retry
HTTP.doRequestOnce = function(url) {
    
    return new Promise((resolve , reject)=>{

        let onTimeout = ()=>{
            reject('onTimeout')
        }
        let xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (4 == xhr.readyState) {
                if (xhr.status >= 200 && xhr.status < 300) {
                    resolve(xhr.response)
                } else {
                    reject('request fail')
                }
            }
        };
        
        xhr.open("GET", url, true);
        xhr.setRequestHeader("CONTENT-TYPE", "application/x-www-form-urlencoded");
        xhr.timeout = 5000;// 5s
        // 网络层的超时与错误统一走超时
        onTimeout && (xhr.ontimeout = onTimeout);
        onTimeout && (xhr.onerror = onTimeout);
        xhr.send();
    })
    
};
HTTP.doRequestRetry = function(url , times){
    console.log('HTTP.doRequestRetry' , url , times)
    return HTTP.doRequestOnce(url)
    .then((response)=>{
        return Promise.resolve(response)
    })
    .catch((err)=>{
        let bRetry = times > 0
        return bRetry ? HTTP.doRequestRetry(url , times - 1) : Promise.reject(err)
    })
}

运行如下(自动重试3次)

 

 

同样原理的setTimeout的超时demo

timeout设置为3.5

因此testClass.setDelays(1 ,2)两秒后未超时输出fail

testClass.setDelays(1 ,4)四秒后超时输出suc

// 超时重试n次的demo
/**
 * 失败
 * testClass.setDelays(1 ,2)
.then(()=>{
    console.log('suc')
})
.catch(()=>{
    console.warn('fail')
})
VM205:14 setDelays 1 2 undefined
Promise {<pending>}
VM205:8 setDelay.setTimeout timeTotal 2.5
VM205:14 setDelays 1 1 1
VM205:8 setDelay.setTimeout timeTotal 1.5
VM230:6 fail


 成功
testClass.setDelays(1 ,4)
.then(()=>{
    console.log('suc')
})
.catch(()=>{
    console.warn('fail')
})
VM205:14 setDelays 1 4 undefined
Promise {<pending>}
VM205:8 setDelay.setTimeout timeTotal 2.5
VM205:14 setDelays 1 3 1
VM205:8 setDelay.setTimeout timeTotal 1.5
VM205:14 setDelays 1 2 2
VM205:8 setDelay.setTimeout timeTotal 0.5
VM205:14 setDelays 1 1 3
VM205:8 setDelay.setTimeout timeTotal -0.5
VM222:3 suc
 */

let testClass = {
    timeout : 3.5 , 
    // second 秒后响应是否超时(比较timeout)
    setDelay : function(second , timePassed = 0){
        let timeRemain = testClass.timeout - timePassed
        return new Promise((resolve , reject)=>{
            window.setTimeout(()=>{
                timeRemain -= second;
                console.log('setDelay.setTimeout timeTotal' , timeRemain)
                resolve(timeRemain < 0)
            } , second * 1000)
        })
    } , 
    // second 秒后响应是否超时
    // 若未超时,重试times次,每次间隔second 秒
    setDelays : function(second , times , timePassed = 0){
        console.log('setDelays' , second , times , timePassed)
        let promise = testClass.setDelay(second , timePassed)
        return promise.then((state)=>{
            if(state){
                return Promise.resolve()
            }
            else if(--times > 0){
                return testClass.setDelays(second , times , ++timePassed)
            }
            else{
                return Promise.reject()
            }
        })
    }
}
View Code