为什么我的try catch块没有捕获Promise.promisifyAll对象抛出的fs.renameSync异常

时间:2018-11-28 05:36:19

标签: node.js error-handling promise try-catch bluebird

代码非常简单。 ks3 is a library其他人发展了。它具有下载文件的启动功能。它使用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块无法捕获到那个?

我进一步检查了the start() implementation。它使用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);
        }
    }
})

------更新-------

我用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代码,或者我将不得不使用domain来捕获异常。我知道domain is deprecated。但是对于这个特定的问题,我发现它是适当的b / c,我确切地知道是什么引起了该问题,并且目前我也没有解决该问题(b / c,这是我无法控制的npm模块)。

1 个答案:

答案 0 :(得分:1)

有关其他上下文,请参见try/catch block not catching async/await error,但要回答有关如何捕获 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引发异常(在调用或安排回调之前),因此您需要将 that 调用包装在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函数曾经抛出(请参阅https://github.com/caolan/async/blob/master/lib/auto.js),但是https://github.com/ks3sdk/ks3-nodejs-sdk/blob/master/lib/api/download.js 确实如果fs方法失败,则抛出该错误,如您所见。

因此,除了a)修复ks3或b)也许,除了找到{{ 1}}永远不会抛出。在这两个中,(a)对我来说听起来容易很多,我认为它应该看起来像这样:

fs

最重要的是,我假设这是一个错误,即如果发生错误 并且存在回调,则ks3代码不会删除配置文件。