Почему мой блок try catch не перехватил исключение fs.renameSync, выданное моим объектом Promise.promisifyAll - PullRequest
0 голосов
/ 28 ноября 2018

Код довольно прост. ks3 - это библиотека , разработанная кем-то другим.Он имеет функцию запуска для загрузки файлов.Для этого используется async.auto.Я оборачиваю его синей птицей Promise.promisifyAll

let ks3p = Promise.promisifyAll(ks3) //ks3 has a start function
try {
    await ks3p.startAsync(param)
} catch (err) {
    //failed to catch fs.renameSync
}

Но иногда я получаю сообщение об ошибке

fs.js:115
    throw err;
    ^
Error: ENOENT: no such file or directory, rename ... -> ...
    at Object.renameSync (fs.js:591:3)

Так почему блок try catch не смог это перехватить?

Iдалее проверил реализацию start () .Он использует async для загрузки файлов, но ничего особенного.

async.auto({
    step_1 : ...
    step_2 : ...
    },
    function(err, results) {
    if (err) {
        if (cb) {
            cb(err, results)
        } else {
            fs.unlinkSync(configFile);
            throw err;
        }
    } else {
        fs.unlinkSync(configFile);
        fs.renameSync(downFileName, filePath);
        if (cb) {
            cb(err, {msg:'success',path:filePath}, null);
        }
    }
})

------ update -------

Часть причины IОберните с Promise.promisifyAll, я не знаю, как отловить эту ошибку.Мой оригинальный код был такой

ks3.download.start(param, (err, result) => {
    //But how do I catch the exception start throw asynchronously ?
    if (err) {
        // error handling 
    } else {
        log(`finished download ${file}`)
    }
    done()
})

------ update2 -------

После дальнейшего изучения вопроса (ответ полезен) я нахожу либо ямодифицированные коды KS3 или мне придется использовать домен, чтобы поймать исключение.Я знаю, домен устарел .Но для этой конкретной проблемы я нахожу это подходящим, потому что я точно знаю, что вызывает проблему, и я также не решаю эту проблему в настоящее время (b / c, это модуль npm, который я не контролирую).

1 Ответ

0 голосов
/ 28 ноября 2018

См. блок try / catch, не перехватывающий ошибку async / await , для получения дополнительного контекста, но чтобы ответить на ваш вопрос о том, как отловить ошибку в un -обещанная версия, вы должны понимать стек вызовов при возникновении ошибки.

У вас было

ks3.download.start(param, (err, result) => {
    //But how do I catch the exception start throw asynchronously ?
    if (err) {
        // error handling 
    } else {
        log(`finished download ${file}`)
    }
    done()
})

, о котором вы должны думать как:

var cb = (err, result) => {
    //But how do I catch the exception start throw asynchronously ?
    if (err) {
        // error handling 
    } else {
        log(`finished download ${file}`)
    }
    done()
});

ks3.download.start(param, cb);

и это start само по себе вызывает исключение (задолго до того, как доходит до вызова или планирования вашего обратного вызова), поэтому вам нужно обернуть этот вызов в try-catch:

var cb = (err, result) => {
    //But how do I catch the exception start throw asynchronously ?
    if (err) {
        // error handling 
    } else {
        log(`finished download ${file}`)
    }
    done()
});

try {
    ks3.download.start(param, cb);
} catch (ex) {
    // here.
}

Хотя я немного подозрительно отношусь к обработке исключений async.auto, и я боюсь, что она может запускать что-то генерирующее асинхронно без перехвата ошибок.В частности, не похоже, что функция callback когда-либо throw (см. https://github.com/caolan/async/blob/master/lib/auto.js),, но https://github.com/ks3sdk/ks3-nodejs-sdk/blob/master/lib/api/download.js делает throw, еслиfs методы терпят неудачу, как вы видите.

Таким образом, вы ничего не можете сделать, кроме a) исправить ks3 или b) возможно найти способ обезьяны-исправьте версию fs, которую ks3 не увидит никогда.Из этих двух, (a) звучит намного проще для меня, и я думаю, что это должно выглядеть примерно так:

async.auto({
    // ...
}, 
function(err, results) {
    if (cb) {
        if (err) {
            cb(err);
            return;
        }
        try {
            fs.unlinkSync(configFile);
            fs.renameSync(downFileName, filePath);
        } catch (ex) {
            cb(ex);
            return;
        }
        cb(err, {msg:'success', path:filePath}, null);
    } else {
        // really, i wouldn't even bother fix this case and just make cb required.
    }
})

Кроме того, я предполагаю, что это ошибка, что код ks3не удаляет файл конфигурации, если есть ошибка и есть обратный вызов.

...