代码之家  ›  专栏  ›  技术社区  ›  Qiulang

为什么我的try-catch块没有捕获由我的Promise.promisifyAll对象引发的fs.renameSync异常

  •  0
  • Qiulang  · 技术社区  · 7 年前

    代码非常简单。 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);
            }
        }
    })
    

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

    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()
    })
    

    在进一步挖掘这个问题后(答案很有帮助),我发现要么修改了ks3代码,要么必须使用域来捕获异常。我知道 domain is deprecated . 但对于这个特定问题,我发现它是合适的b/c我确切地知道问题的原因,我目前也没有解决这个问题(b/c它是一个npm模块,我无法控制)。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Rob Starling    7 年前

    看见 try/catch block not catching async/await error 有关其他上下文,请回答您关于如何在 -在promisified版本中,当抛出错误时,您必须了解调用堆栈。

    你有

    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 ),但是 https://github.com/ks3sdk/ks3-nodejs-sdk/blob/master/lib/api/download.js 如果 fs

    因此,除了修复之外,你什么也做不了 ks3 或b) 找到一种方法来修补版本的 财政司司长 ks3

    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 如果出现错误,代码不会删除配置文件 有人回电话了。

    推荐文章