async waterfall步骤出错后的重试

async给nodejs开发者们提供了很好的异步转同步的方法, 其中就以waterfall的应用最为广泛,waterfall的典型用法如下:


var async = require("async");
async.waterfall(
[
//step1
function (cb) {
    console.log("step1");
    cb(null);
},
//step2
function (cb) {
    console.log("step2");
    cb(null);
},
//step3
function (cb) {
    console.log("step3");
    cb(null);
}
],
function (e) {
    console.log("complete, ", e);
}
);

这段代码以可控顺序输出:

step1
step2
step3
complete

但是有时候我们有这种需求:当step2执行出错时,我想重试最多两次step2,如果还出错,才跳到complete,而不是一出错就直接跳到complete。对于这种需求我是这么处理的:

var async = require("async");
var retrystep = 0;
async.waterfall(
[
//step1
function (cb) {
    console.log("step1");
    cb(null);
},
//step2
// 首先需要给step2函数命名,不能是匿名函数
function step2(cb) {
    console.log("step2, retry=", retrystep);
    //这里执行实际的逻辑过程,返回result
    var result = false;// do_something();

    //如果result错误,且重试次数小于3次,则继续执行step2
    if (!result && retrystep < 2) {
        //记录下增加的重试次数
        retrystep++;
        //再次执行step2,注意要带上参数cb
        step2(cb);
    }
    else {
        //如果执行正确就下一步
        if (result) {
            cb(null);
        }
        //否则就直接跳到结束complete
        else {
            cb("step2 error");
        }
    }
},
//step3
function (cb) {
    console.log("step3");
    cb(null);
}
],
//complete
function (e) {
    console.log("complete, ", e);
}
);

这段代码输出:

step1
step2, retry= 0
step2, retry= 1
step2, retry= 2
complete,  step2 error

step2执行了3次,这是重试自己这一步骤的情况,但是如果我重试上一步骤怎么办呢?根据上面的方法,我们很自然想到在step2中调用step1函数,如下:

var async = require("async");
var retrystep = 0;
async.waterfall(
[
//step1
function step1(cb) {
    console.log("step1");
    cb(null);
},
//step2
// 首先需要给step2函数命名,不能是匿名函数
function step2(cb) {
    console.log("step2, retry=", retrystep);
    //这里执行实际的逻辑过程,返回result
    var result = false;// do_something();


    //如果result错误,且重试次数小于3次,则继续执行step2
    if (!result && retrystep < 2) {
        //记录下增加的重试次数
        retrystep++;
        //再次执行step2,注意要带上参数cb
        step1(cb);
    }
    else {
        //如果执行正确就下一步
        if (result) {
            cb(null);
        }
        //否则就直接跳到结束complete
        else {
            cb("step2 error");
        }
    }
},
//step3
function (cb) {
    console.log("step3");
    cb(null);
}
],
//complete
function (e) {
    console.log("complete, ", e);
}
);

但是这段代码是有问题的,首先step2函数里面是调用不到step1函数的,其次调用step1的参数cb并不是step1的参数,所以要解决这个问题,我们就要设法在step2里面可以得到step1和其参数,我是这么实现的:

var async = require("async");
var retrystep = 0;
var state = {};
async.waterfall(
[
//step1
//同样step1需要命名
function step1(cb) {
    //这里记录下step1函数名和参数,保存在state中,用于在每个步骤中传递
    state.step1 = step1;
    state.step1cb = cb;
    console.log("step1, retry=", retrystep);
    cb(null);
},
//step2
// 首先需要给step2函数命名,不能是匿名函数
function step2(cb) {
    console.log("step2, retry=", retrystep);
    //这里执行实际的逻辑过程,返回result
    var result = false; // do_something();


    //如果result错误,且重试次数小于3次,则再次从step1执行起
    if (!result && retrystep < 2) {
        //记录下增加的重试次数
        retrystep++;
        //再次从step1执行起来,同样要带上保存的参数step1cb
        state.step1(state.step1cb);
    }
    else {
        //如果执行正确就下一步
        if (result) {
            cb(null);
        }
        //否则就直接跳到结束complete
        else {
            cb("step2 error");
        }
    }
},
//step3
function (cb) {
    console.log("step3");
    cb(null);
}
],
//complete
function (e) {
    console.log("complete, ", e);
}
);

以上这段代码输出如下:

step1, retry= 0
step2, retry= 0
step1, retry= 1
step2, retry= 1
step1, retry= 2
step2, retry= 2
complete,  step2 error
step1和step2各执行了3次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值