用promisifyAll 无法运行then里面的function

写了一个demo:

class Box{
    constructor(name){
        this.name = name; 
    }
    run(){
      console.log(this.name + ' is running')
    }
}

var bluebird = require('bluebird');
var box = bluebird.promisifyAll(new Box('ss'));

box.runAsync().then(function(){
    console.log('stop');
})


按理说应该要打印出

ss is running
stop

但是只能打印出

ss is running

请问为什么?

阅读 3.3k
3 个回答

你看文档的话会发现一个词叫做nodeFunction,需要promisify的方法必须要满足nodeFunction的定义,其中一条就是回调函数作为最后一个参数,也就是说这个函数一定有作为回调函数的参数并且这个参数位于所有参数的最后。

The target methods are assumed to conform to node.js callback convention of accepting a callback as last argument and calling that callback with error as the first argument and success value on the second argument.

在你的例子中,run函数是没有回调参数的,所以也就无法判断这个promise是什么时候完成的,所以then里面的代码就不会执行,修改后的代码如下:

class Box{
    constructor(name){
        this.name = name; 
    }
    run(callback) {
      console.log(this.name + ' is running')
      callback()
    }
}

var bluebird = require('bluebird');
var box = bluebird.promisifyAll(new Box('ss'));

box.runAsync().then(function(){
    console.log('stop');
})

.. 不太清楚你想干什么

没用过 bluebird, 大概看了下大多用在 nodejs 里面把 callback 转变为 promise 化。你这里 boxrun 方法连形参都没有转成 promise 又有什么意义呢。你发现了最后 then 不执行,那你有没有想过 then 应该什么时候去执行呢。就算你是为了简单的实验一下 run 方法也应该写成你熟悉的异步模块的函数,至少有一个回掉函数吧

class Box{
    constructor(name){
        this.name = name; 
    }
    run(cb){
      console.log(this.name + ' is running')
      cb(null) // null 代表没有错误 
    }
}

其实你可以自己尝试一下这个库要怎么把 callback 的函数转变为 promise 对象,自己简单来写可以会这样

let box = new Box('ss')

let runAsync = (...args) => new Promise((r, j) => {
    box.run.call(box, ...args, (err, data) => {
        if (err) return j(err)
        r(data)
    })
})

runAsync().then(function(){
    console.log('stop');
})

可以看到如果你最后一个回掉函数都没有,生产的 promise 就跟本没有触发错误或者成功的时机

根据上面的提示,终于弄懂了。
promisifyAll会把对象里面所有的函数包括原型都包裹成一个promise

重写了一下:

class Box{
    constructor(name){
        this.name = name; 
    }

    delayOne(cb){
      setTimeout(function(){
        console.log('delay 1s')
        cb();
      }, 1000)
      
    }

    delayTwo(cb){
        setTimeout(function(){
          console.log('delay 2s');
          cb();
        }, 2000)
        
      }
}

var bluebird = require('bluebird')
var box = bluebird.promisifyAll(new Box('ss'));

box.delayTwoAsync().then(function(){
   return box.delayOneAsync();
}).then(function(){
    console.log('stop');
});

结果

delay 2s
delay 1s
stop

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏