【Node100In1】01.去异步,解决掉Node.js万恶的回调陷阱

Node.js是基于事件驱动编程。异步函数随处可见,其中不乏一些常用库的方法。本例就以js中最常见的setTimeout的为例,试图改善一下回调的书写。

先来看一段伪代码:

我们实现一个需求,每隔一段时间打印一段字符串,按照一般的同步设计思维,那么大概是这个样子:

; i < ; i++)
{
    sleep(i);
    printf("out:%d", i);
}

但是在js中可就没这么简单了。首先,类似sleep的setTimeout函数睡眠之后的事件就在回调当中

setTimeout(function(){

},1000)

看到这我想大家也都明白了,这要是写在循环里,很难受,写起来很难受。用递归是一种方法,但是也难受。

解决这个问题的办法要借助node的两样工具:

1.Promise

2.async/await (需要node8 版本)

Promise主要用来优化回调函数的书写格式,使得多次回调的嵌套不会写那么多层。

上述循环的单次循环可以封装成如此格式:

function call_once(_i)
{
    setTimeout(function(_i){
        return ("out:"+_i)
    },_i*1000)
}

Promise不在node官方库中 ,需要使用npm安装,Promise有很多三方包,个人比较常用的是 bluebird

npm install bluebird
const promise = require('bluebird')

对上边的call_once方法封装,就是:

function call_once(_i)
{
    return new promise(function(resolve){
        setTimeout(function(){

            resolve("out:" + _i)

        }, _i*1000)
    })
}

但是这个方法也不能直接当同步方法用,回调后的内容需要写在 promise对象的then方法当中:

call_once(1).then(function(_result){

    console.log(_result);

})

没错,所有在这条主线上执行的内容都需要不断的用这个promise的对象then下去,写在外边是不行的。会提前执行。

所以还是没法把这个东西嵌入到for循环当中,这个时候就需要await/async了。

1.首先把所有的异步内容全部嵌套到一个异步函数当中,声明异步函数需要在function前声明关键字async。

2.在需要阻塞的函数前(这个函数需要返回promise对象)加上await关键字:

async function looper(){
    for(let i = 0; i < 5; i++)
    {
        await call_once(i).then(function(_result)
        {
                console.log(_result)
        })
    }
}

如此就实现了for-sleep的方法。但是要注意,还是只限在lopper()方法当中才是同步的,写在looper外边的内容还是不行。TAT。如果是一些小功能脚本的话,就把looper当main方法用吧。

最后祝您,身体健康。再见

------------------------------------------------------>

to be continued

上一篇:原生JS实现全屏切换以及导航栏滑动隐藏及显示——重构前


下一篇:Luogu P1477 [NOI2008]假面舞会