I am using Promise.all to run two separate functions which in themselves are maps running a function within a Promise.all multiple times.
async function nonBlockingWithMapAndArray(): Promise<any> {
let arr = [100,200,150];
let arr2 = [500,1000,300]; // <--- value of 1000 causes an error to be thrown
console.log(`nonBlockingWithMapAndArray: starting...`);
const pa = await Promise.all([
await iterateArrayAndCall(arr),
await iterateArrayAndCall(arr2) // <--- This throws an error
])
.then( (data) => {
console.log(`nonBlockingWithMapAndArray: In then...`);
})
.catch((err) => { // <-- This should catch the error but does not, instead the error goes up to main which calls nonBlockingWithMapAndArray()
console.log('nonBlockingWithMapAndArray: In catch', err);
});
console.log(`nonBlockingWithMapAndArray: Finished`);
return pa;
}
The solution I have works correctly when no errors are thrown. However, if an error is thrown, the catch of the Promise.all does not catch the error and instead it propagates up to the main calling app.
In this code, the 2nd function call iterateArrayAndCall(arr2)
throws an error. But it is not caught by the catch
on the Promise.all
.
Any help would be appreciated. Full code below...
bootstrap();
async function bootstrap() {
let res;
try {
res = await nonBlockingWithMapAndArray();
} catch (err) {
console.log('Main: In catch'); // <-- This is where the error is caught
}
}
async function nonBlockingWithMapAndArray(): Promise<any> {
let arr = [100,200,150];
let arr2 = [500,1000,300]; // <--- value of 1000 throws an error
console.log(`nonBlockingWithMapAndArray: starting...`);
const pa = await Promise.all([
await iterateArrayAndCall(arr),
await iterateArrayAndCall(arr2) // <--- This throws an error
])
.then( (data) => {
console.log(`nonBlockingWithMapAndArray: In then...`);
})
.catch((err) => { // <-- This should catch the error but does not
console.log('nonBlockingWithMapAndArray: In catch', err);
});
console.log(`nonBlockingWithMapAndArray: Finished`);
return pa;
}
async function iterateArrayAndCall(arr: any) : Promise<any> {
return await Promise.all(
arr.map( async (element) => {
await delayAndGetRandomPromWithError(element); //If element is 1000 an error will be generated
})
)
.then((data) => {
console.log(`iterateArrayAndCall: in then...`);
})
.catch((err) => {
console.log(`iterateArrayAndCall: in catch`);
throw new Error('Failed in iterateArrayAndCall');
// Also tried:
// return Promise.reject();
// return err
});
}
async function delayAndGetRandomPromWithError(ms): Promise<number> {
console.log(`MS start :${ms}`);
if( ms === 1000 ) {
throw new Error('1000 so throw error...');
}
const p: Promise<number> = new Promise(resolve =>
setTimeout(() => {
const val: number = Math.trunc(Math.random() * 100);
console.log(`MS finish :${ms}`);
resolve(val);
}, ms
));
return p;
};
async function throwOne() {
console.log(`Am I blocking?`);
throw new Error(`Test error`);
}
Output when run
nonBlockingWithMapAndArray: starting...
MS start :100
MS start :200
MS start :150
MS finish :100
MS finish :150
MS finish :200
iterateArrayAndCall: in then...
MS start :500
MS start :1000
MS start :300
iterateArrayAndCall: in catch
Main: In catch <--- I expect to see this here instead .... 'nonBlockingWithMapAndArray: In catch'
MS finish :300
MS finish :500