在使用Node.js实现爬虫、检测等功能时,经常会遇到大量网络请求的情况,这时很容易因为超时而使得请求失败。为令结果正确,我们一般会设置一定的失败重试次数,以避免因网络波动引起的失败。若多次尝试最终失败,才抛出错误。
下面上一段代码:
/**
* 包裹方法,使其自动错误重试
* 只能包裹返回Promise的方法
* 返回promise,可以获取成功的返回值,或最后失败的err
* 需要运行环境支持ES6的Promise语法,或者使用Bluebird库
* @param func
* @param retryMax
* @returns {funcR}
*/
function autoRetry(func, retryMax) {
retryNum = 0;
let funcName = func.toString().match(/function (\w+)\(/)[1];
return funcR = function () {
let params = arguments;
return new Promise((resolve, reject) => {
func(...params).then(result => {
resolve(result);
}).catch(err => {
if (retryNum < retryMax) {
retryNum ++;
console.warn(`[autoRetry] Catched error when ${funcName}() : ${err.message}. Retry ${retryNum} time...`);
resolve(funcR(...params));
} else {
reject(err);
}
});
});
};
}
使用起来很简单。下面举一个例子:
// 这是一个标准的Promise化的方法
function foo (param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
try{
JSON.parse('{{'); // 执行到这里会报错
return resolve(param);
} catch (err) {
return reject(err);
}
}, 1000);
})
}
// 使用autoRetry()包裹方法,并给出最大重试次数(执行数=重试次数+1)
foo = autoRetry(foo, 3);
// 执行并获取结果/捕获错误
foo(123)
.then(r => {
console.log('成功返回:');
console.log(r)
})
.catch(e => {
console.log('最后错误:');
console.log(e)
})
// 也可以这样写
(async function (){
try {
let result = await foo(123);
} catch (e) {
console.log(e);
}
})();