该代码非常简单。 ks3 is a library其他人开发的。它具有启动功能来下载文件。它使用async.auto来做到这一点。
我用bluebird 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()
})

------更新2 -------

进一步研究问题之后(答案很有帮助),我发现我修改了ks3代码,或者必须使用domain来捕获异常。我知道domain is deprecated。但是对于这个特定的问题,我发现它是适当的b/c,我确切地知道是什么引起了该问题,并且目前我也没有解决该问题(b/c,这是我无法控制的npm模块)。

最佳答案

有关其他上下文,请参见try/catch block not catching async/await error,但是要回答有关如何在 promise 的版本中捕获错误的问题,则必须在引发错误时了解调用堆栈。

你有过

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函数曾经抛出过(请参见https://github.com/caolan/async/blob/master/lib/auto.js),但是如果fs方法失败,https://github.com/ks3sdk/ks3-nodejs-sdk/blob/master/lib/api/download.js确实会抛出,就像您看到的那样。

因此,除了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代码不会删除配置文件。

09-26 09:25