为什么我的 try catch 块没有捕捉到 Promise.promisifyAll 对象抛出的 fs.renameSync 异常
Why my try catch block didn't catch the fs.renameSync exception thrown by my Promise.promisifyAll object
代码非常简单。 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. It uses 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 is deprecated。但是对于这个特定的问题,我发现它是合适的 b/c 我确切地知道是什么导致了这个问题,我现在也没有解决这个问题(b/c 这是一个 npm 模块,我无法控制) .
有关其他上下文,请参阅 ,但要回答有关如何捕获 un 中的错误的问题-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
本身抛出异常(在调用或安排回调之前的方式),因此您需要包装 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
函数永远 throw (参见 https://github.com/caolan/async/blob/master/lib/auto.js), but https://github.com/ks3sdk/ks3-nodejs-sdk/blob/master/lib/api/download.js does throw如果 fs
方法失败,如您所见。
因此,除了 a) 修复 ks3
或 b) 也许 找到一种猴子修补 [=17 版本的方法之外,您无能为力=] 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
代码不会删除配置文件 并且 有一个回调.
代码非常简单。 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. It uses 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 is deprecated。但是对于这个特定的问题,我发现它是合适的 b/c 我确切地知道是什么导致了这个问题,我现在也没有解决这个问题(b/c 这是一个 npm 模块,我无法控制) .
有关其他上下文,请参阅
你有
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
函数永远 throw (参见 https://github.com/caolan/async/blob/master/lib/auto.js), but https://github.com/ks3sdk/ks3-nodejs-sdk/blob/master/lib/api/download.js does throw如果 fs
方法失败,如您所见。
因此,除了 a) 修复 ks3
或 b) 也许 找到一种猴子修补 [=17 版本的方法之外,您无能为力=] 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
代码不会删除配置文件 并且 有一个回调.