Javascript Promise.all可捕获错误的包装器
我用一个简单的脚本逐字记录:Javascript Promise.all可捕获错误的包装器,javascript,node.js,ecmascript-6,es6-promise,Javascript,Node.js,Ecmascript 6,Es6 Promise,我用一个简单的脚本逐字记录: Promise.all(links.map(function (l) { return Promise.resolve(require(l).r2gSmokeTest()) .then((v:any) => ({path: l, result: v})); })) .then(function(results){ }) .catch(function(e){ }): 问题是,如果require()调用出于任何原因抛出错误,承诺链将无法捕获它
Promise.all(links.map(function (l) {
return Promise.resolve(require(l).r2gSmokeTest())
.then((v:any) => ({path: l, result: v}));
}))
.then(function(results){
})
.catch(function(e){
}):
问题是,如果require()
调用出于任何原因抛出错误,承诺链将无法捕获它
要避免这种情况,最简单的方法是将Promise.all包装到一个函数中,如下所示:
const getAllPromises = function(links){
return Promise.resolve(null).then(function(){
return Promise.all(links.map(function (l) {
return Promise.resolve(require(l).r2gSmokeTest())
.then((v:any) => ({path: l, result: v}));
}));
在我看来,maybe Promise.all应该有不同的API,比如:
Promise.all(function(){
return values.map(v => whatever);
});
这样,如果在承诺链中未调用Promise.all,则任何错误都可能被捕获…使用不能抛出的
异步函数
,它只会在发生异常时返回被拒绝的承诺:
Promise.all(links.map(async function (l) {
const v: any = await require(l).r2gSmokeTest();
return {path: l, result: v};
}))
一般来说,对于任何执行异步操作的函数来说,期望总是返回一个承诺和。您的
map
callback应该遵守这一点,并且try…catch(e){return Promise.reject(e);}
在require
调用(如有必要)周围。您也可以考虑使用类似于.E/P>< P>的帮助函数,使用不能抛出的<代码>异步函数 -它只会在异常发生时返回拒绝的承诺:
Promise.all(links.map(async function (l) {
const v: any = await require(l).r2gSmokeTest();
return {path: l, result: v};
}))
一般来说,对于任何执行异步操作的函数来说,期望总是返回一个承诺和。您的map
callback应该遵守这一点,并且try…catch(e){return Promise.reject(e);}
在require
调用(如有必要)周围。您也可以考虑使用帮助函数,如 < p>您的<代码>要求()/代码>发生在承诺上下文之外的映射级别上,这就是为什么它立即被传播到全局级别,因此如果您将其包装成<代码>新承诺< /代码>,它应该按照预期处理错误:
Promise.all(links.map(function(l) {
return new Promise(resolve => resolve(require(l).r2gSmokeTest())) // <-- here
.then((v: any) => ({
path: l,
result: v
}));
}))
.then(function(results) {
})
.catch(function(e) {
}):
Promise.all(links.map)(函数(l){
返回新承诺(resolve=>resolve(require(l).r2gSmokeTest())//({
路径:l,
结果:v
}));
}))
.然后(函数(结果){
})
.catch(函数(e){
}):
您的require()
发生在Promise上下文之外的映射级别上,这就是它会立即传播到全局级别的原因,因此,如果您只是将其包装到一个新Promise
中,它应该按照预期处理错误:
Promise.all(links.map(function(l) {
return new Promise(resolve => resolve(require(l).r2gSmokeTest())) // <-- here
.then((v: any) => ({
path: l,
result: v
}));
}))
.then(function(results) {
})
.catch(function(e) {
}):
Promise.all(links.map)(函数(l){
返回新承诺(resolve=>resolve(require(l).r2gSmokeTest())//({
路径:l,
结果:v
}));
}))
.然后(函数(结果){
})
.catch(函数(e){
}):
你的问题到底是什么?@Bergi好像你明白了,抱歉没有那么清楚你的问题到底是什么?@Bergi好像你明白了,抱歉没有那么清楚,但是如果你答应了。all()。那么()在这种情况下,如果在异步
函数中出现错误,然后
是否会兑现承诺?我不确定它是否能通过我的测试,这是有效的,但我不确定为什么。如果您进一步解释它工作的原因,那就很好了,但是如果您确实承诺.all().then(),那么在这种情况下,then
是否会在async
函数中出现错误时遵守承诺?我不确定它是否能通过我的测试,这是有效的,但我不确定为什么。如果你能详细解释一下它为什么会起作用,我认为使用Promise.resolve(null)
进行包装比使用执行者创建新的承诺更简单?@Olegzandr这取决于“simple”的定义,我认为“simple”意味着在尽可能少地更改源代码的情况下解决问题。如果你的不同,请澄清。请记住,Promise.resolve(arg)
是newpromise(resolve=>resolve(arg))的别名
,每个。然后都在链中创建一个新的Promise对象。这就是为什么在某种意义上调用newpromise()
更简单的原因,因为您不必创建额外的承诺,也不必输入像null
这样神奇的占位符值。我认为使用Promise.resolve(null)
包装比与执行者一起创建新承诺更简单?@Olegzandr好吧,这取决于“简单”的定义,我认为“简单”意味着在尽可能少地更改源代码的情况下解决问题。如果你的不同,请澄清。请记住,Promise.resolve(arg)
是newpromise(resolve=>resolve(arg))的别名
,每个。然后都在链中创建一个新的Promise对象。这就是为什么在某种意义上调用newpromise()
更简单的原因,因为您不必创建额外的承诺,也不必输入像null
这样的神奇占位符值。