Reputation: 1534
I am trying to setup a way of executing promises in a sequential way. I have followed one of the tutorials online and came up with this:
return promises.reduce((promiseChain, currentTask) => {
return promiseChain.then(chainResults => {
return currentTask.then(currentResult => {
return [ ...chainResults, currentResult ];
}).catch(error => {
errors.push(error);
return;
});
});
}, Promise.resolve([])).then(arrayOfResults => {
console.log("ARRAY_OF_RESULTS", arrayOfResults);
return errors.length > 0 ? response.status(400).send(errors) : response.status(200).send("De advertenties zijn succesvol verstuurd naar alle partner portalen");
});
});
However, somehow, once in a while I get the following warning in my terminal console:
(node:10894) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 62)
(node:10894) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 62)
ARRAY_OF_RESULTS undefined
(node:10894) UnhandledPromiseRejectionWarning: #<Object>
(node:10894) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 71)
(node:10894) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 71)
How can we prevent this from happening?
If you need any additional information or need an invite to the project please do not hesitate to ask me. I know that additional information is probably needed to further debug this question.
When I change the return call in the catch of one of my promises like below it won't show the error.
```//return { status: error.response.status, partner: "autoscout", message: error.response.statusText };
return Promise.reject({ status: error.response.status, partner: "autoscout", message: error.response.statusText })```
Upvotes: 0
Views: 70
Reputation: 664297
The problem is that you already have started all of the actions at once, and placed their resulting promises into a promises
array. Nothing in here is running sequentially. You should just write
Promise.allSettled(promises).then(arrayOfResults => {
console.log("ARRAY_OF_RESULTS", arrayOfResults);
const errors = arrayOfResults.filter(res => res.status == "rejected").map(res => res.reason);
if (errors.length > 0)
response.status(400).send(errors);
else
response.status(200).send("De advertenties zijn succesvol verstuurd naar alle partner portalen");
});
If you actually wanted to execute your actions sequentially, you would need to start each individual action inside the reduce
callback. Currently, with currentTask.then(…)
you are only hooking onto the resolution events in sequence, but the actions were started long ago - and when a promise is getting rejected you might not yet have hooked onto it, causing the unhandled rejection. So you'll want to put a task - a function that returns a promise - in that array:
const tasks = []; // an array of functions to be run sequentially
if(autoscoutEnabled) {
tasks.push(() => createAutoscoutAd("/vehicles", jsonAutoscout, "tokenteststring"));
tasks.push(() => addImageToAutoscoutAd("/vehicles/7e59591f-c5a3-974e-e452-2951040ae4ee", file, type, "tokenteststring"));
}
if (marktplaatsEnabled) {
tasks.push(() => createMarktplaatsAd("/advertisements", jsonMarktplaats, "tokenteststring"));
tasks.push(() => addImageToMarktplaatsAd("/advertisements/m1427566569", file, type, "tokenteststring"));
}
return tasks.reduce((promiseChain, currentTask) => {
return promiseChain.then(errors => {
const currentPromise = currentTask();
// this is the important line ^^
return currentPromise.then(() => errors, error => {
errors.push(error);
return errors;
});
});
}, Promise.resolve([])).then(errors => {
console.log("ARRAY_OF_RESULTS", arrayOfResults);
if (errors.length > 0)
response.status(400).send(errors);
else
response.status(200).send("De advertenties zijn succesvol verstuurd naar alle partner portalen");
});
However, for sequential execution I would recommend to use async
/await
, which is much simple to work with.
Upvotes: 1