bluebird Promise.promisifyAll 可以在 promisify 该对象的函数失败时工作
bluebird Promise.promisifyAll can work while promisify a function of that object fails
我尝试承诺 SFTPWrapper 并解决了这个问题。我不确定它是否发生在其他对象上。
因此,如果我只是 promisify
一个 SFTPWrapper 函数,比如 readdir
,bluebird 将具有 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)
您没有准确显示错误 "Cannot read property 'readdir' of undefined error" 发生的位置。如果出现在这行代码:
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
永远不是好的错误处理。从字面上看,您永远不应该在异步回调中编写该行代码,除非该异步回调的调用者具有针对该异常的显式处理程序(通常情况并非如此)。它所做的只是将异常抛出到异步遗忘中,没有机会在代码中的其他任何地方进行实际错误处理。
我尝试承诺 SFTPWrapper 并解决了这个问题。我不确定它是否发生在其他对象上。
因此,如果我只是 promisify
一个 SFTPWrapper 函数,比如 readdir
,bluebird 将具有 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)
您没有准确显示错误 "Cannot read property 'readdir' of undefined error" 发生的位置。如果出现在这行代码:
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
永远不是好的错误处理。从字面上看,您永远不应该在异步回调中编写该行代码,除非该异步回调的调用者具有针对该异常的显式处理程序(通常情况并非如此)。它所做的只是将异常抛出到异步遗忘中,没有机会在代码中的其他任何地方进行实际错误处理。