Reputation:
I have this verbatim in a simple script:
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){
}):
the problem is that if the require()
call throws an error for whatever reason, the promise chain won't catch it.
is the simplest thing to do to avoid this to wrap Promise.all in a function, like so:
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}));
}));
it seems to me that maybe Promise.all should have a different API, something like:
Promise.all(function(){
return values.map(v => whatever);
});
that way any errors can be trapped, if Promise.all is not called within a Promise chain...
Upvotes: 0
Views: 256
Reputation: 5422
Your require()
is happening on the map level outside of Promise context, that's why it gets propagated immediately to the global level, so if you just wrap it into a new Promise
it should handle the error as expected:
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) {
}):
Upvotes: 1
Reputation: 664237
Use an async function
which can't throw - it will only return a rejected promise when an exception happens:
Promise.all(links.map(async function (l) {
const v: any = await require(l).r2gSmokeTest();
return {path: l, result: v};
}))
In general, the expectation for any function that does something asynchronous is to always return a promise and never throw synchronously. Your map
callback should adhere to that - and try … catch (e) { return Promise.reject(e); }
around the require
call if necessary. You might also consider using a helper function that works like Bluebird's Promise.try
.
Upvotes: 1