我尝试承诺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)
答案 0 :(得分:2)
您没有确切显示错误“无法读取未定义错误的属性'readdir'”的发生位置。如果它出现在以下代码行中:
let readdirAsync = util.promisify(sftp.readdir);
然后,问题是sftp
是undefined
。但是,这似乎并不是问题所在,因为您说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
永远不会带来很好的错误处理。从字面上看,您永远不要在异步回调内编写该行代码,除非该异步回调的调用者具有针对该异常的显式处理程序(通常不是这种情况)。它所做的一切就是将异常抛出到异步遗忘中,而没有机会在代码中的其他任何地方进行实际的错误处理。