Bluebird Promise.promisifyAll может работать, пока не удается выполнить функцию обещания этого объекта - PullRequest
0 голосов
/ 31 октября 2018

Я пытаюсь обещать 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)

1 Ответ

0 голосов
/ 31 октября 2018

Вы не указываете, где именно возникает эта ошибка «Невозможно прочитать свойство readdir неопределенной ошибки». Если это происходит в этой строке кода:

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

Тогда проблема в том, что sftp равно undefined. Но, похоже, проблема не в этом, потому что вы говорите, что const sftp2 = Promise.promisifyAll(sftp) работает.

Итак, я предполагаю, что проблема возникает, когда вы пытаетесь использовать readdirAsync. Если это так, то это, вероятно, потому, что вы потеряли родителя sftp, когда сделали let readdirAsync = util.promisify(sftp.readdir), и это как-то важно для реализации метода 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 внутри асинхронного обратного вызова НИКОГДА не является хорошей обработкой ошибок. Вы буквально никогда не должны писать эту строку кода внутри асинхронного обратного вызова, если только вызывающая сторона этого асинхронного обратного вызова не имеет явного обработчика для этого исключения (что обычно не имеет место). Все, что он делает - это бросает исключение в асинхронное забвение, не имея возможности для фактической обработки ошибок где-либо еще в вашем коде.

...