探究 node.js async模块流程控制

使用async进行代码流程控制

最近学习node流程控制需要用到async模块里的各种函数,这里先剖析一小部分,日后慢慢加工,以下就是我的学习心路,刚开始写博客,求各位大佬指导指导,也希望有小伙伴与我一起学习交流

race(tasks, callback)

官方文档的说明如下:
Runs the tasks array of functions in parallel, without waiting until the previous function has completed. Once any of the tasks complete or pass an error to its callback, the main callback is immediately called. It’s equivalent to Promise.race().
大概意思就是,同时执行一组函数,当有一个回调完成或报错,主回调函数立即执行。
代码走起

const async = require('async');
function task1(callback){
    setTimeout(()=>{
        console.log("task1 is done")
        callback(null,'task1');
    },1000)
} 
function task2(callback){
    setTimeout(()=>{
        console.log("task2 is done")
        callback(null,'task2');
    },2000)
} 
function task3(callback){
    setTimeout(()=>{
        console.log("task3 is done")
        callback(null,'task3');
    },3000)
} 
function task4(callback){
    setTimeout(()=>{
        console.log("task4 is done")
        callback(null,'task4');
    },1000)
} 
function task5(callback){
    setTimeout(()=>{
        console.log("task5 is done")
        callback(null,'task5');
    },1000)
} 
async.race([task1,task2,task3,task4],function(err,result){
    if(err){
        console.log(err);
    }else{
        console.log(`result in the main callback`);
    }
})
//执行效果如下
C:\Users\Administrator\Desktop\资料\毕设\hello-koa2\demo>node asyncDemo.js
task1 is done
result in the main callback
task4 is done
task2 is done
task3 is done

因为task1最快,所以task1回调后主回调也随之调用。这种比较简单基本看了就懂,还是挑一些复杂点的研究研究。。

auto (tasks, concurrencyopt, callbackopt)

官方说明如下:
Determines the best order for running the AsyncFunctions in tasks, based on their requirements. Each function can optionally depend on other functions being completed first, and each function is run as soon as its requirements are satisfied.
If any of the AsyncFunctions pass an error to their callback, the auto sequence will stop. Further tasks will not execute (so any other functions depending on it will not run), and the main callback is immediately called with the error.
AsyncFunctions also receive an object containing the results of functions which have completed so far as the first argument, if they have dependencies. If a task function has no dependencies, it will only be passed a callback.
意思大概就是,可以很安排一组异步函数中的某些函数3,在函数1,2完成后才开始执行,如果执行中有其中一个异步函数抛出错误则停止整组函数,并调用主回调,函数执行时可以接受它所依赖的函数完成时的结果组成的一个数组,也就是这个函数执行之前所执行了的函数的结果集会当做第一个参数传入这个函数。上代码

console.time("Tasks")
function task1(callback){
    setTimeout(()=>{
        console.log("task1 is done")
        callback(null,'task1');
    },1000)
} 
function task2(callback){
    setTimeout(()=>{
        console.log("task2 is done")
        callback(null,'task2');
    },2000)
} 
function task3(results,callback){
    console.timeEnd("Tasks");
    setTimeout(()=>{
        console.log(`task3 is done,results is${JSON.stringify(results)}` )
        
        callback(null,'task3');
    },3000)
} 
async.auto({
    task1 : task1,
    task2 : task2,
    task3 : ['task1','task2',task3]
},(err,results)=>{
    if(err){
        console.log(`${err} is emerged,${JSON.stringify(results)} in the main callback`);
    }else{
        console.log(`${JSON.stringify(results)} in the main callback`);
    }
})
//运行结果
C:\Users\Administrator\Desktop\资料\毕设\hello-koa2\demo>node asyncDemo.js
task1 is done
task2 is done
Tasks: 2003.854ms
task3 is done,results is{"task1":"task1","task2":"task2"}
{"task1":"task1","task2":"task2","task3":"task3"} in the main callback

不难看出,task1,task2是并行执行的,一共用了2s,然后执行task3,且task3收到了task1,task2的结果集作为参数,主回调收到了整个结果集。这里的callback调用的是我们在async.auto()中,最后定义的那个函数,(err,results)=>{},这里我们将task1中的callback(null,“task1”)改为callback(“error”,“task1”)会得到如下输出。

//输出
task1 is done
error is emerged,{"task1":"task1"} in the main callback
task2 is done

可以看出第一轮执行的是task1,task2.然后task3需要等待,然后task1利用callback抛了一个错误,导致任务提前结束触发了主回调的响应,然后又过了1S,task2执行结束打印了一条语句。总得来说async.auto()这个方法主要给一组有依赖关系的异步调用。例如我们平时有的人喜欢睡觉前听歌看书,那么听歌=task1,看书=task2,前面这两个任务结束后,我们开始睡觉,执行task3;

auto函数其实还可以加一个并发执行任务数量的最大值限定的参数,很容易理解,这里就不说了

总觉得代码命名还欠点什么,再看看

retry(optsopt, task, callbackopt)

看函数名都可以看出来这是个不断尝试直到成功或超时的函数。
直接上代码:

扫描二维码关注公众号,回复: 5690505 查看本文章
function tryToGetNumber8(callback){
    setTimeout(()=>{
        let num = Math.floor(Math.random()*9);
        console.log(num)
        if(num === 8){
            callback(null,'successful get 8');
        }else{
            callback('error',`failed,last time get ${num}`);
        }
        
    },100)
} 
async.retry(10,tryToGetNumber8,(err,result)=>{
    if(err){
        console.log(result);
    }else{
        console.log(result);
    }
})
//第一次运行结果
C:\Users\Administrator\Desktop\资料\毕设\hello-koa2\demo>node asyncDemo.js
5
4
8
successful get 8
//第二次运行结果
C:\Users\Administrator\Desktop\资料\毕设\hello-koa2\demo>node asyncDemo.js
3
2
7
6
4
3
2
6
0
6
failed,last time get 6

可以看出,这个函数可以在有限次数内发送异步请求直到成功,还有以下一些用法

console.time("task")
async.retry({times:10,interval:200},tryToGetNumber8,(err,result)=>{
    if(err){
        console.log(result);
    }else{
        console.timeLog("task")
        console.log(result);
    }
})
//运行结果
C:\Users\Administrator\Desktop\资料\毕设\hello-koa2\demo>node asyncDemo.js
1
8
task: 408.829ms

上面的用法使用{times:10,interval:200}替代了原来的次数,增加了一个间隔时间指定,看上面的结果可以看出,第一次任务执行了100ms没有成功,过了200ms后再次发送请求执行了100ms后成功得到了8,返回,一共花费400ms。

retry还可以进行错误过滤,如果执行错误是制定错误则再次执行请求。

function tryToGetNumber8(callback){
    setTimeout(()=>{
        let num = Math.floor(Math.random()*9);
        console.log(num)
        if(num === 8){
            callback(null,'successful get 8');
        }else if(num < 4){
            callback('小于4',`failed,last time get ${num}`);
        }else{
            callback('error',`failed,last time get ${num}`);
        }
        
    },100)
} 
console.time("task")
async.retry({
    errorFilter: function(err) {
        return err === '小于4'; 
    }},
    tryToGetNumber8,
    (err,result)=>{
    if(err){
        console.log(result);
    }else{
        console.timeLog("task")
        console.log(result);
    }
})
//运行结果
C:\Users\Administrator\Desktop\资料\毕设\hello-koa2\demo>node asyncDemo.js
0
3
2
5
failed,last time get 5

从上面结果可以看出,小于四的错误都被过滤后继续重新请求,当出现非小于4的错误时任务就停止了。

async包的函数还有许多,各位需要使用node进行流程控制的可以尝试一下,比较好上手,功能也挺全面。值得研究

猜你喜欢

转载自blog.csdn.net/A6107907/article/details/86438267
今日推荐