美文网首页
在node.js 中使用async await

在node.js 中使用async await

作者: yaya520 | 来源:发表于2017-10-18 11:45 被阅读0次

    一、历史

    在用node.js编写程序代码时通常会遇到很多的异步操作,对于异步的处理,大概经历了以下几种方法:
    1、回调。也就是第一个参数是error的函数,那么如果嵌套的层数多了,也就感觉特别非人类了,读起来会非常困难。

    mongoDb.open(function(err, db){
        if(!err){
            db.collection("users", function(err, collection){
                if(!err){
                    let person = {name: "yika", age: 20};
                    collection.insert(person, function(err, result){
                        if(!err){
                            console.log(result);
                        }
                    });
                }
            })
        }
    });
    

    2、Promise。我们也可以称作链式操作。从以下代码可以看出代码的可读性已经大大改善。但是我们仍然不可忽视某些问题,Promise 的最大问题是代码冗余,原来的任务被 Promise 包装了一下,不管什么操作,一眼看去都是一堆then,原来的语义变得很不清楚。

    let person = {name: "yika"};
    mongoDb
        .open()
        .then(function(database){
          return database.collection("users");
        })
        .then(function(collection){
          return collection.insert(person);
        })
        .then(function(result){
          console.log(result);
        })
        .catch(function(e){
          throw new Error(e);
        })
    

    3、Generator。借着ES6的Generator迭代器,最早实现了异步编程同步化的功能,也就是最为我们所熟知的co库。我们通过co(function *(){})可以使函数内部通过迭代器来控制。而co在这里则是充当了启动器的角色。
    参考:Generator 函数的异步应用

    let co = require("co");
    co(function *(){
        let db, collection, result; 
        let person = {name: "yika"};
        try{
            db = yield mongoDb.open();
            collection = yield db.collection("users");
            result = yield collection.insert(person);
        }catch(e){
            console.error(e.message);
        }
        console.log(result);
    });
    

    4、async/await。直接上代码。

    async function insertData(person){
        let db, collection, result; 
        try{
            db = await mongoDb.open();
            collection = await db.collection("users");
            result = await collection.insert(person);
        }catch(e){
            console.error(e.message);
        }
        console.log(result);
    } 
    insertData({name: "yika"});
    

    我们可以看到inserData是一个真正的函数,是我们可以直接去调用而无需启动器驱动的。当然内部我们也可以感受到处理yield变成了await以外,并没有很大区别。async/await,更符合我们异步编程的语义。
    参考:async 函数

    二、使用

    babel已经支持async的transform了,所以我们使用的时候引入babel就行。
    在开始之前我们需要引入以下的package,其中babel-plugin-transform-runtime是babel的一个支持es7async的插件。 es7不同阶段语法提案的转码规则共有4个阶段,分别是babel-preset-stage-0,babel-preset-stage-1,babel-preset-stage-2,babel-preset-stage-3。选装一个就行,我这里用的是babel-preset-stage-3。

    npm install babel-core --save-dev
    npm install babel-preset-es2015 --save-dev
    npm install babel-preset-stage-3 --save-dev
    npm install babel-plugin-transform-runtime --save-dev
    

    我们使用官方提供的require hook方法,顾名思义就是通过require进来后,接下来的文件进行require的时候都会经过Babel的处理。因为我们知道CommonJs是同步的模块依赖,所以也是可行的方法。我们需要多一个用于启动的js文件,一个真正执行程序的js文件。

    // index.js 
    // 用于引入babel,并且启动app.js
    require("babel-core/register");
    require("./app.js");
    require("babel-core").transform("code", {
        plugins: ["transform-runtime"]
    });
    

    配置完hook之后,我们就配置babel的.babelrc文件,它是一个在项目根目录的json格式的文件。(在windows系统中新建文件名为以.开头的文件,如.babelrc,只需将文件名写为.babelrc.即可)

    {
        "presets": [
            "stage-3",
            "es2015"
        ],
        "plugins": [
            [
                "transform-runtime",
                {
                    "helpers": false,
                    "polyfill": false,
                    "regenerator": true,
                    "moduleName": "babel-runtime"
                }
            ]
        ]
    }
    

    我们的异步代码写在app.js中即可。

    相关文章

      网友评论

          本文标题:在node.js 中使用async await

          本文链接:https://www.haomeiwen.com/subject/edesuxtx.html