Node.js 异步流程控制

Node.js 异步流程控制

异步流程控制对象async

  • 串行无关联:async.series
  • 并行无关联:async.parallel
  • 串行有关联:waterfall
  • parallelLimit:parallelLimit函数和parallel类似,但是他多了一个参数limit
  • limit参数限制任务只能同时并发一定数量,而不是无限制并发

首先我们需要安装async模块:
这里写图片描述

这里写图片描述

我们来看看同步的情况:

function oneFun(){

    console.log("oneFun");
}


function twoFun(){
    console.log("twoFun");
}


oneFun();
twoFun();

console.log("end");

这里写图片描述

方法同步执行。

现在我们来写一个异步的例子:

function oneFun(){

    var i = 0;
    /*
    setTimeout(function(){
        console.log("oneFun");
    },1000);//1秒之后调用
    */
    setInterval(function(){
        console.log("oneFun");
        i++;
        if(i == 3){
            clearInterval(this);
        }
    },1000);//每隔1秒调用一次
}


function twoFun(){
    var j = 0;
    setInterval(function(){
        console.log("twoFun");
        j++;
        if(j == 3){
            clearInterval(this);
        }
    },1000);//每隔1秒调用一次

}


oneFun();
twoFun();

console.log("end");

这里写图片描述

我们发现两个方法交叉执行。
如果我们想要oneFun执行完在执行twoFun的话,我们需要如下改写代码:

function oneFun(){

    var i = 0;
    /*
    setTimeout(function(){
        console.log("oneFun");
    },1000);//1秒之后调用
    */
    setInterval(function(){
        console.log("oneFun");
        i++;
        if(i == 3){
            clearInterval(this);
            twoFun();//等待oneFun执行完回调
        }
    },1000);//每隔1秒调用一次
}


function twoFun(){
    var j = 0;
    setInterval(function(){
        console.log("twoFun");
        j++;
        if(j == 3){
            clearInterval(this);
        }
    },1000);//每隔1秒调用一次

}


oneFun();


console.log("end");

这里写图片描述

我们发现实现了我们想要的,但是如果我们要执行的方法很多,就需要回调中继续嵌套回调,这样看起来很乱而且难以维护。

async.series

我们接下来用async.series来改造:

var async = require('async');

function exec(){
//串行无关联
    async.series(
        {   //这里面是串行的方法
            one : function(done){
                //回调函数写在这 
                done(null,'one完毕');//done执行完之后才会执行two函数
            },
            two : function(done){
                done(null,'two完毕');
            }
        },function(err,rs){
            console.log(err);
            console.log(rs);
        }   
    )
}

exec();

console.log("end");

这里写图片描述

var async = require('async');

function exec(){
//串行无关联
    async.series(
        {   //这里面是串行的方法
            one : function(done){
                //回调函数写在这 
                done('错误','one完毕');//只要done不执行就不会执行下一个函数
            },
            two : function(done){
                done(null,'two完毕');
            }
        },function(err,rs){
            console.log(err);
            console.log(rs);
        }   
    )
}

exec();

console.log("end");

这里写图片描述
所以出现错误之后,下一个函数two就不执行了。

var async = require('async');

function exec(){
//串行无关联
    async.series(
        {   //这里面是串行的方法
            one : function(done){
                //回调函数写在这 
                var i = 0;
                /*
                setTimeout(function(){
                    console.log("oneFun");
                },1000);//1秒之后调用
                */
                setInterval(function(){
                    console.log("oneFun");
                    i++;
                    if(i == 3){
                        clearInterval(this);
                        done(null,'one完毕');
                    }
                },1000);//每隔1秒调用一次
            },
            two : function(done){
                    var j = 0;
                    setInterval(function(){
                        console.log("twoFun");
                        j++;
                        if(j == 3){
                            clearInterval(this);
                            done(null,'two完毕');
                        }
                    },1000);//每隔1秒调用一次
            }
        },function(err,rs){
            console.log(err);
            console.log(rs);
        }   
    )
}

exec();

console.log("end");

这里写图片描述
我们可以看出oneFun执行完毕之后,two才开始执行

  • series可以接受数组作为参数,需要串行处理的方法作为数组的元素。
var async = require('async');

async.series(
    [
        function (callback) {
            setTimeout(function () {
                console.log('event A occurs')
                callback(null, 'A')   // 第一个参数是异常错误,第二个参数是返回值
            }, 3000)
        },
        function (callback) {
            console.log('event B occurs');
            callback(null, 'B')
        }
    ], function (err, results) {
        // results是返回值的数组
        console.log('event ' + results[0] + results[1] + ' occurs')
    }
)
console.log("event D occurs")

这里写图片描述

  • async.series也可以接受对象作为参数,代码如下:
var async = require('async');
async.series(
    {
        A: function (callback) {
            setTimeout(function () {
                console.log('event A occurs')
                callback(null, 'A')   // 第一个参数是异常错误,第二个参数是返回值
            }, 3000)
        },
        B: function (callback) {
            console.log('event B occurs');
            callback(null, 'B')
        }
    }, function (err, results) {
        // results是所有的返回值合集,results.A获取的是A的返回值。
        console.log('event ' + results.A + results.B + ' occurs')
    }
)
console.log("event D occurs")

这里写图片描述

var async = require('async');

function exec(){
//串行无关联
    async.series(
        {   //这里面是串行的方法
            one : function(done){
                //回调函数写在这 
                var i = 0;
                /*
                setTimeout(function(){
                    console.log("oneFun");
                },1000);//1秒之后调用
                */
                setInterval(function(){
                    console.log("oneFun");
                    i++;
                    if(i == 3){
                        clearInterval(this);
                        done('错误','one完毕');
                    }
                },1000);//每隔1秒调用一次
            },
            two : function(done){
                    var j = 0;
                    setInterval(function(){
                        console.log("twoFun");
                        j++;
                        if(j == 3){
                            clearInterval(this);
                            done(null,'two完毕');
                        }
                    },1000);//每隔1秒调用一次
            }
        },function(err,rs){
            console.log(err);
            console.log(rs);
        }   
    )
}

exec();

console.log("end");

这里写图片描述

oneFun的done出现错误,所以被拦截了,所以twoFun就不会执行。

注意:如果任何一个方法在callback中返回了一个异常错误,停止后续方法的执行,且async.series的回调立即执行。

async.parallel

  • async.parallel可以接受对象作为参数
var async = require('async');
function exec(){
//并行无关联
    async.parallel(
        {   
            one : function(done){
                //回调函数写在这 
                var i = 0;
                /*
                setTimeout(function(){
                    console.log("oneFun");
                },1000);//1秒之后调用
                */
                setInterval(function(){
                    console.log("oneFun");
                    i++;
                    if(i == 3){
                        clearInterval(this);
                        done(null,'one完毕');
                    }
                },1000);//每隔1秒调用一次
            },
            two : function(done){
                    var j = 0;
                    setInterval(function(){
                        console.log("twoFun");
                        j++;
                        if(j == 3){
                            clearInterval(this);
                            done(null,'two完毕');
                        }
                    },1000);//每隔1秒调用一次
            }
        },function(err,rs){
            console.log(err);
            console.log(rs);
        }   
    )
}

exec();

console.log("end");

这里写图片描述

  • async.parallel可以接受数组作为参数
var async = require('async');

async.parallel(
    [
        function (callback) {
            setTimeout(function () {
                console.log('event A occurs')
                callback(null, 'A')
            }, 3000)
        },
        function (callback) {
            console.log('event B occurs')
            callback(null, 'B')
        }
    ], function (err, result) {
        console.log("event C occurs")
         console.log(result)
    }
)
console.log("event D occurs")

这里写图片描述

var async = require('async');
function exec(){
//并行无关联
    async.parallel(
        {   
            one : function(done){
                //回调函数写在这 
                var i = 0;
                /*
                setTimeout(function(){
                    console.log("oneFun");
                },1000);//1秒之后调用
                */
                setInterval(function(){
                    console.log("oneFun");
                    i++;
                    if(i == 3){
                        clearInterval(this);
                        done('错误','one完毕');
                    }
                },1000);//每隔1秒调用一次
            },
            two : function(done){
                    var j = 0;
                    setInterval(function(){
                        console.log("twoFun");
                        j++;
                        if(j == 3){
                            clearInterval(this);
                            done(null,'two完毕');
                        }
                    },1000);//每隔1秒调用一次
            }
        },function(err,rs){
            console.log(err);
            console.log(rs);
        }   
    )
}

exec();

console.log("end");

这里写图片描述

注意:
1、并行执行,所有任务执行完后,立即执行回调函数。
2、如果有一个任务执行异常报错,立即执行回调函数。

async.waterfall

waterfall:串行,前一个任务的结果传递给后一个任务。

var async = require('async');

function exec(){
    async.waterfall(
        [   
            function(done){
                //回调函数写在这 
                var i = 0;
                /*
                setTimeout(function(){
                    console.log("oneFun");
                },1000);//1秒之后调用
                */
                setInterval(function(){
                    console.log("oneFun");
                    i++;
                    if(i == 3){
                        clearInterval(this);
                        done(null,'one完毕'); // 第一个参数是error,第二个参数是下一个任务的参数
                    }
                },1000);//每隔1秒调用一次
            },
            function(preValue,done){
                    var j = 0;
                    setInterval(function(){
                        console.log("twoFun");
                        j++;
                        if(j == 3){
                            clearInterval(this);
                            done(null,preValue + ',two完毕');
                        }
                    },1000);//每隔1秒调用一次
            }
        ],function(err,rs){
            console.log(err);
            console.log(rs);
        }   
    )
}

exec();

console.log("end");

这里写图片描述

var async = require('async');

function exec(){
    async.waterfall(
        [   
            function(done){
                //回调函数写在这 
                var i = 0;
                /*
                setTimeout(function(){
                    console.log("oneFun");
                },1000);//1秒之后调用
                */
                setInterval(function(){
                    console.log("oneFun");
                    i++;
                    if(i == 3){
                        clearInterval(this);
                        done(null,'one完毕');
                    }
                },1000);//每隔1秒调用一次
            },
            function(preValue,done){
                    var j = 0;
                    setInterval(function(){
                        console.log(preValue + "twoFun");
                        j++;
                        if(j == 3){
                            clearInterval(this);
                            done(null,preValue + ',two完毕');
                        }
                    },1000);//每隔1秒调用一次
            }
        ],function(err,rs){
            console.log(err);
            console.log(rs);
        }   
    )
}

exec();

console.log("end");

这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值