Bluebird中promisify的用法

1 篇文章 0 订阅
1 篇文章 0 订阅

Bluebird中promisify的用法

之前应项目需要,在node.js中引入bluebird包学习使用Promise。其链式结构的异步操作容易理解,也减少了回调函数的多层嵌套。网络上对Promise的介绍已经比较全面,这里不再赘述。本文主要从实际工作遇到的问题出发,介绍其promisify方法的使用。

New一个Promise对象的缺点

创建一个新的Promise对象代码如下:

var Promise = require('bluebird');
var promiseObj = new Promise(function(resolve, reject) {
    var isJudged = false,
        result = '';
    // some logic deal code
    // ...
    // get judgement 
    if (isJudged) {
        resolve(result);
    }
    else if (!isJudged) {
        reject('Something wrong');
    }
});

我们知道Promise对象存在三种状态:Pending,Resolved和Rejected。当我们的代码执行完一系列的操作,最后进行判断需不需要将运算出的结果返还回去,如果需要,那么我们使用resolve(result);这句代码返回结果,如果不需要,那么我们使用reject(‘Something wrong’);这句代码返回错误信息。二者决定我们在使用此Promise对象时的.then方法是进入Resolved状态的Function还是Rejected状态的Function。

var z = promiseObj.then(function(result){
    // Resolved 
}, function(error) {
    // Rejected
});

从上面代码可以读出,PromiseObj包含一个then方法,then方法中通过自身状态决定使用哪一个回调函数,那么PromiseObj中存在一个属性保存自身的状态,这条状态的值依赖于我们在new Promise对象时所传入的function中的代码。

实际上,我们在new Promise对象时,传入的function中的代码就立即执行了,Promise对象迫不及待地想得到一个状态值(Resolved也好Rejected也好)。在某些场景应用中,这并非我们所想要的。比如在不同流程中都包含同样一个步骤的Promise,在每个流程中我们都需要重新new一个相同的Promise对象来保证每个流程的运转正常。假如我们只使用一个Promise,那么这个Promise在new出来的那一刻起,就获取当前的context变量开始运行,期望得到一种结果状态。而对于不同流程,它们各自的context变量是存在差异的,因而使用同一个Promise对象会产生预估之外的问题,而对不同流程使用不同Promise的做法看上去又相当麻烦且代码冗长。

我们需要一种Promise型的对象(异步且可用.then的形式执行回调函数),这时候我们可以使用promisify方法。

Promisify

promisify旨在解决使用Promise的方式调用那些没有使用Promise的模块中的方法。这么说可能比较绕。请看官网上解释promisify使用方法的一段代码:

var readFile = Promise.promisify(require("fs").readFile);

readFile("myfile.js", "utf8").then(function(contents) {
    return eval(contents);
}).then(function(result) {
    console.log("The result of evaluating myfile.js", result);
}).catch(SyntaxError, function(e) {
    console.log("File had syntax error", e);
//Catch any other error
}).catch(function(e) {
    console.log("Error reading file", e);
});

这里将fs模块中读取文件的readFile转化为了Promise形式的异步方法。现实应用这样的场景也不少,我们需要将一个之前定义好的方法转化为异步的形式。下面将详细介绍如何使用promisify。

var Promise = require('bluebird');

var normalFn = function(a, b, c, cb) {
    /**
     *  your own logic code
     */
    var t = a + b + c;
    if (typeof cb == 'function') {
        cb('', t);
    }
};

var promisifyFn = Promise.promisify(normalFn);
promisifyFn('hello, ', 'world', '!').then(function(result){
    console.log(result);
}, function(error) {
    console.log(error);
});

根据上例,我们必须满足以下条件方可使用promisify进行转换。

  • 原方法必须包含回调函数(cb(”, t);
  • 必须执行回调函数,目的是决定在完成中间整块逻辑代码后,获取最终方法的的状态(Resolved或Rejected)以便选择进入哪个真实的.then之后的回调函数。
  • 回调函数第一个参数代表error的信息,第二个参数代表成功时返回的结果。error为空值,则后续可进入Resoleved的方法,若不为空值,则后续进入Rejected方法

不同于声明一个Promise对象,我们在声明一个promisifyFn时并不会立即去执行其间的逻辑代码,而是将一个普通的函数转化为了一个返回Promise对象的函数,当我们真正调用这个函数的时候,其间的代码才真正的运行。

官网对其定义如下:

Promise.promisify(
    function(any arguments..., function callback) nodeFunction,
    [Object {
        multiArgs: boolean=false,
        context: any=this
    } options]
) -> function

我们在使用promisify时可以设定一些参数,比如context执行上下文,和multiArgs。如果multiArgs设定为true,那么我们在执行cb(”, t);时可以传入多个成功的值,即除了第一个参数绑定为error以外,我们可以在后续的参数中加入我们想添加的任何对象。最终这些传入的参数反应为执行Resolved函数的参数,即.then(function(result) { console.log(result); },。multiArgs为true,那么result是cb传入参数的一个数组对象;multiArgs为false,那么result是cb传入参数的第二个,尽管cb会传入大于两个的参数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值