蓝鸟Promise.promisifyAll可以工作,而承诺该对象的功能失败

时间:2018-10-31 04:31:22

标签: node.js promise es6-promise bluebird

我尝试承诺SFTPWrapper并解决此问题。我不确定是否发生在其他物体上。

因此,如果我仅promisify个SFTPWrapper函数,例如readdir,则蓝鸟将拥有unhandledRejection : "Cannot read property 'readdir' of undefined" error。我尝试了util.promisify,同样的错误。

但是如果promisifyAll(SFTPWrapper)可以正常工作。但是为什么呢?

----更新-----

我使用的代码

var Client = require('ssh2').Client
var conn = new Client()
conn.on('ready', function() {
    conn.sftp(async function(err, sftp) {
        if (err) throw err
        try {
          // promisify will have Cannot read property 'readdir' of undefined error
          // both bluebird and util have the error

          //let readdirAsync = Promise.promisify(sftp.readdir)
          let readdirAsync = util.promisify(sftp.readdir)
          list = await readdirAsync(remotePathToList)

         // Promise.promisifyAll(sftp) work
         const sftp2 = Promise.promisifyAll(sftp)
         let list = await sftp2.readdirAsync(toRead)

1 个答案:

答案 0 :(得分:2)

您没有确切显示错误“无法读取未定义错误的属性'readdir'”的发生位置。如果它出现在以下代码行中:

let readdirAsync = util.promisify(sftp.readdir);

然后,问题是sftpundefined。但是,这似乎并不是问题所在,因为您说const sftp2 = Promise.promisifyAll(sftp)确实有效。

因此,我猜测当您尝试使用readdirAsync时会出现问题。如果真是这样,那可能是因为您在执行let readdirAsync = util.promisify(sftp.readdir)时丢失了sftp父级,这对readdir方法实现很重要。如果确实如此,则可以执行以下操作:

let readdirAsync = util.promisify(sftp.readdir).bind(sftp);

确保父对象保持绑定到方法。因为Bluebird的.promisifyAll()将新方法放在原始对象上,并且您将它们作为对象上的方法而不是普通函数来调用,所以当您以sftp2.readdirAsync()调用它们时,对原始对象的绑定会自动发生。您也可以按照以下步骤进行操作:

sftp.readdirAsync = util.promisify(sftp.readdir);

然后,您可以调用sftp.readdirAsync(...).then(...).catch(...)并将它们适当地绑定到sftp对象。

P.S。在异步回调中使用if (err) throw err永远不会带来很好的错误处理。从字面上看,您永远不要在异步回调内编写该行代码,除非该异步回调的调用者具有针对该异常的显式处理程序(通常不是这种情况)。它所做的一切就是将异常抛出到异步遗忘中,而没有机会在代码中的其他任何地方进行实际的错误处理。