面试遇到的问题
当场竟然没写出来
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() } }) } }