回调形式的流程控制 async库的使用
发布于 1 年前 作者 blackjack 1160 次浏览 最后一次编辑是 6 个月前 来自 分享

一个关于node流程控制的问题,喜欢写回调模式的可以看过来 async包括 顺序执行(series),瀑布流执行(waterfall),并行执行(parallel)(parallelLimit)这几个应该是常用的 直接上代码了,本人用的是async库

var async = require('async');
async.series([
	function(cb){
		setTimeout(function(){
			cb(null, 1);
		}, 1000);
	},
	function(cb){
		setTimeout(function(){
			cb(null, 2);
		}, 1000);
	}
], function(error, result){
	if(error){
		console.log(error);return;
	}
	console.log('parallel:消耗时间为数组的每个方法执行时间的总合, result的结果为每个方法的返回结果,和数组顺序对应');
	console.log('parallel:',result);
});

/*并行执行*/
async.parallel([
	function(cb){
		setTimeout(function(){
			cb(null, 1);
		}, 1000);
	},
	function(cb){
		setTimeout(function(){
			var c = 1 + 100;
			cb(null, c);
		}, 1000);
	}
], function(error, result){
	if(error){
		console.log(error);return;
	}
	console.log('parallel:消耗时间为数组中的执行最长的一个方法, result的结果为每个方法的返回结果,和数组顺序对应');
	console.log('parallel:', result);
});


/*paramllelLimit参数是三个,第二个则为限制并行的数量*/
async.parallelLimit([
	function(cb){
		setTimeout(function(){
			cb(null, 1);
		}, 1000);
	},
	function(cb){
		setTimeout(function(){
			var c = 1 + 100;
			cb(null, c);
		}, 1000);
	}
], 1, function(error, result){
	if(error){
		console.log(error);return;
	}
	console.log('parallelLimit:消耗时间为数组中的执行最长的一个方法, result的结果为每个方法的返回结果,和数组顺序对应');
	console.log('parallelLimit:', result);
});
11 回复

promise之前async是首选,个人也挺喜欢这个库

login(user, pass, function(result) {
    doSomeThing(result, function(err) {
        switch(err) {
        case 'disconnect':
            goto login;
        case 'retry':
            goto doSomeThing;
        default:
            logout(function() {
                console.log('finish');
            }
        }
    }
}

就这个例子,怎么用async或promise?

@gzhangzy

loginAync(user, pass).then(function(result){
 	return doSomeThing(result)
}).then(function(err){

}).catch(function(err){
})

要实现那句 goto doSomeThing 的逻辑,怎么办呀?

@gzhangzy


async.series([user, pass], function(error, result){
	doSomeThine(result, function(err){
	
	});
});

这样也可以吧

问的是 那两个goto逻辑 怎么实现?

promise大法好,generator大法好

可以运行验证,大法也就那么回事。

var Steps = require("promise-tiny/Steps");

new Steps({
    user: 'foo',
    pass: 'foolish',
    loginCount: 0,
    doSomeThingCount: 0
}) .on('Begin', function(next) {	// 从这里开始
        next('login', [this.user, this.pass]);
    })
   .on('login', function(next, user, pass) {
        console.log('login("'+user+'", "'+pass+'")');

        this.loginCount++;

        var result = true;	// 假设login总能成功
        console.log('    第'+this.loginCount+'次login成功');
        console.log();
        next('doSomeThing', '一些要做的事情...');
    })
   .on('doSomeThing', function(next, ...args) {
        console.log('doSomeThing("'+args+'")');

        this.doSomeThingCount++;

        if(this.doSomeThingCount === 1) {	// 假设第一次做不成功,重试一次
            console.log('    第'+this.doSomeThingCount+'次doSomeThing失败,再试一次');
            next('doSomeThing', args);
        }
        else if(this.loginCount === 1) {	// 假设第二次做不成功,重新login
            console.log('    第'+this.doSomeThingCount+'次doSomeThing失败,重新login');
            next('login', [this.user, this.pass]);
        }
        else {
            console.log('    第'+this.doSomeThingCount+'次doSomeThing完成了,要退出了');
            next('logout');
        }
        console.log();
    })
   .on('logout', function(next) {
        console.log('logout()');
    })

运行结果

login("foo", "foolish")
    第1次login成功

doSomeThing("一些要做的事情...")
    第1次doSomeThing失败,再试一次

doSomeThing("一些要做的事情...")
    第2次doSomeThing失败,重新login

login("foo", "foolish")
    第2次login成功

doSomeThing("一些要做的事情...")
    第3次doSomeThing完成了,要退出了

logout()

@gzhangzy 用Promise写的:

var loginCount = 0;
var doSomeThingCount = 0;

var login = function () {
  return new Promise(function (resolve, reject) {
    loginCount++;
    console.log('login: %d', loginCount);
    resolve(doSomeThing());
  });
};

var logout = function () {
  return new Promise(function (resolve, reject) {
    console.log('logout');
    resolve('logout');
  });
};

var doSomeThing = function () {
  return new Promise(function (resolve, reject) {
    doSomeThingCount++;
    console.log('doSomeThing: %d', doSomeThingCount);

    if (doSomeThingCount === 1) {
      resolve(doSomeThing());
    } else if (loginCount === 1) {
      resolve(login());
    } else {
      resolve(logout());
    }
  });
};

login().then(function (result) {
  console.log('done');
}).catch(function (err) {
  console.error('error: %j', err);
});

输出:

login: 1
doSomeThing: 1
doSomeThing: 2
login: 2
doSomeThing: 3
logout
done

写的不错!

@gzhangzy 多谢多谢,个人爱好写回调

回到顶部