异常在程序设计的过程中无处不在,也会使我们的程序变得复杂臃肿。简单的do{...}while(1)基本能够实现我们所需要的异常处理,但这个显然不是优雅的node写法。今天自己动手实现一个简单的retry类来实现重试功能。
代码中的异步处理采用co库进行了封装。
retry.js
'use strict';
const maxRetryTimes = 10;
class retry{
constructor(){
}
static *attempt(func, ...args){
let retry = 0;
do{
console.log(`retry time = ${retry}, maxRetryTimes = ${maxRetryTimes}`);
if(retry++ > maxRetryTimes){
console.log('return');
return '';
}
let res = yield func(args);
if(res)
{
return res;
}
}while(1)
}
}
module.exports = retry;
测试代码如下:
app.js
'use strict';
const request = require('request');
const co = require('co');
const derived = require('./derived');
var main = function(){
co(function*(){
let it = new derived();
yield it.entry();
}).then(()=>{
}, (reason)=>{
console.log(reason);
})
}
main();
base.js
'use strict'
const co = require('co');
const retry = require('./retry');
class Base{
constructor(){
this.timeout = 5000;
}
*doSomething(arg){
return '';
}
*getTimeout(){
return this.timeout;
}
*entry(){
yield retry.attempt(this.doSomething, 'https://www.baidu.com', this);
console.log(`attempt end....`);
}
}
module.exports = Base;
derived.js
'use strict';
const co = require('co');
const base = require('./base');
const request = require('co-request');
class derived extends base{
constructor(){
super();
}
*doSomething(arg){
try{
let _this = arg[1];
let timeout = yield _this.getTimeout();
console.log(`timeout = ${timeout}`);
let res = yield request({
uri: arg[0],
method:'GET',
timeout: timeout
});
if(res){
throw new Error(`test errro`);
}
return res.body;
}catch(error){
console.log(`error accur: ${error}`);
}
}
}
module.exports = derived;
如果直接使用retry.attempt在基类中调用派生类方法,派生类此方法中this会失效,不能够获取成员变量或者调用基类或子类方法。解决方法是在使用retry.attempt方法封装重试方法时,将this作为参数传递,方法中使用此参数获取成员。