node Promise (async/await)

在使用exoress 框架开发node项目是,异步调用往往是件很麻烦的事情,所以在闲暇之余就研究了下。。。

一、首先ES6已经支持异步的Promise对象(模式)

1、什么是promise?

  Promise可能大家都不陌生,因为Promise规范已经出来好一段时间了,同时Promise也已经纳入了ES6,而且高版本的chrome、firefox浏览器都已经原生实现了Promise,只不过和现如今流行的类Promise类库相比少些API。

  所谓Promise,字面上可以理解为“承诺”,就是说A调用B,B返回一个“承诺”给A,然后A就可以在写计划的时候这么写:当B返回结果给我的时候,A执行方案S1,反之如果B因为什么原因没有给到A想要的结果,那么A执行应急方案S2,这样一来,所有的潜在风险都在A的可控范围之内了。

Promise规范如下:

  • 一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)

  • 一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换

  • promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致

  • then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象。

2.promise原理分析

  可以看到promise的规范并不是很多,下面我们一边分析promise一边自己写一个promise的实现。Promise实现的大致思路如下:

  构造函数Promise接受一个函数function(resolve,reject),可以理解为传入一个异步任务,resolver接受的是成功时的回调,reject接受的是失败时的回调,这两参数和通过then传入的参数是对等的。

其次是then的实现,由于Promise要求then必须返回一个promise,所以在then调用的时候会新生成一个promise,挂在当前promise的_next上,同一个promise多次调用都只会返回之前生成的_next。

由于then方法接受的两个参数都是可选的,而且类型也没限制,可以是函数,也可以是一个具体的值,还可以是另一个promise。下面是then的具体实现:

例1 构建数据库连接的promise 对象: 见附件dbPool.js

例2 

 async function sendEBEserver(req, res) {

    var serverhost = req.body.service.trim();
    var port = req.body.port.trim();
    var parm = req.body.body.trim();
    logger.info("sys", "begin query parm:" + parm);
    var method = req.body.method.trim() || "post";
    var jwtparm = parseInt(req.body.ison);
    var jwtkey = req.body.string.trim();
    var ul = req.body.url.trim();
    var url = "http://" + serverhost + ":" + port + "/" + ul;
    logger.info("sys", "jwt password:" + jwtkey);
    var times = req.body.times.trim();

    var time_start = new Date().getTime();
    logger.info("receive param  done!!!");
    var ebereq = {
        url: url,
        method: (method ? method : 'POST'),
        json: false,
        timeout: 60 * 1000 * 10
    };

    if (parm) {
        logger.debug("sys original param:" + parm);
        var obj = {};
        obj.gid = new Date().getTime() + "kaka";
        obj.exp = moment().add(1, 'day').unix();
        obj.content = parm;
        obj.areacode3 = "";
        obj.areacode4 = "";
        ebereq.json = false;
        logger.debug("sys before jwt:" + JSON.stringify(obj));
        ebereq.body = parm;
    }
    logger.info("sys", "发送请求参数:" + JSON.stringify(ebereq));
    var result =  await new Promise(function(resolve,reject){
         request(ebereq, function (err, response, body) {
             if (!err && response.statusCode == 200) {
                 if (!ebereq.json && typeof body == "string") {
                     body = JSON.parse(body);
                 }
                 logger.info("sys", "获取到" + url + ",返回的数据:" + JSON.stringify(body));
                 body.time = (new Date().getTime() - time_start) / 1000;
                 body.times = times;
                 resolve(body);
             } else {
                 var error = (err ? err.message : (response.statusCode + ":" + response.statusMessage));
                 logger.error("sys", "获取到" + url + ",返回的错误:" + error);
                 error.status = "请求出错";
                 error.time = (new Date().getTime() - time_start) / 1000;
                 error.times = times;              
                 reject(error);
             }
         });
     })

     logger.debug("sys","request url: "+url+" finished...");
     res.json(returnData.success(result));
}

通过构建promise对象,使request请求按照同步的方式返回。

上述资料来源:http://www.cnblogs.com/yunfeifei/p/4453690.html

其他:关于ES6的新特性,借鉴一个网址:http://www.cnblogs.com/Wayou/p/es6_new_features.html


二、express 项目中使用 async/await处理异步

    1、通过第一部分可以知道要通过使用async/await处理异步逻辑,首先需要将异步过程包装为一个promise对象。注意在包装promise对象时resolve和reject参数。

    2、 要在express项目中使用ES6的async/await关键字处理异步,在项目启动是需添加参数--harmony(此参数是是node支持部分ES6的新特性,但并不是完全支持,所以建议在使用时在此参数后显示ES6特点参数)

   例如:可以通过node  --harmony -async-await  ./bin/www 的方式启动项目来支持 使用ES6的async/await关键字。

              也可以通过pm2启动:pm2 start ./bin/www --node-args="--harmony-async-await"

          在webstrom中也可通过配置启动:

             


注意:在webstrom使用ES6特性时默认编辑默认会async/await关键字报错,所以要修改编译器设置。

你可能感兴趣的:(node,express,ES6,express)