Node.js 异步流程控制

来源:互联网 发布:淘宝老店新开流量限制 编辑:程序博客网 时间:2024/05/17 09:21

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");

这里写图片描述

原创粉丝点击