-1

I got a piece of code that would submit several set of reports which they are independent each other, currently wrote in promise.allSettled, but I was told that the team standard would require async await instead of promise

"Never use multiple await for two or more independent async parallel tasks, because you will not be able to handle errors correctly. Always use Promise.all() for this use case." 1

"In comparison, the Promise returned by Promise.all() may be more appropriate if the tasks are dependent on each other / if you'd like to immediately reject upon any of them rejecting." 2

"Using for await...of, you have more granular control of the promises. So if the order in which promises complete is important to you, for await...of is your preferred choice. However, the increased control isn’t free. The fact that for await...of handles promises one by one, makes it a lot slower." "To sum up, the three methods are all capable of handling iterables of promises, but differ slightly in their functioning. Use for await of if the order in which promises are resolved is important to you. Use Promise.all() if the order isn’t important and you need all calls to succeed. Use Promise.allSettled() if the order isn’t important and you don’t absolutely need all individual calls to be successful." 3

After some research, I found it is not possible to rewrite it in async await with the same efficiency (request execute in parallel) and simplicity (promise.allSettled is a built-in function), am I correct?

That piece of code

const recordInsertErrors:Object[] = [];
await Promise.allSettled(
    jsonArray.map((eachPositionReport) => {
      return PositionReport.query().insert(eachPositionReport).catch((err) => {
        const error = { vessel_ownership_id: eachPositionReport.vessel_ownership_id, error: err.nativeError };
        recordInsertErrors.push(error);
        throw err;
      });
    }),
  );
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
J L
  • 67
  • 2
  • 8
  • This question looks a bit vague. What exactly you tried to do (show code) and where does it not do what you want? – trincot Jul 24 '22 at 08:46
  • 2
    "*I was told that the team standard would require async await instead of promise*" - that sounds like the team doesn't understand promises and/or `async`/`await`. Or maybe they only referred to the usage of `.catch()`, not to the `Promise.allSettled` call? – Bergi Jul 24 '22 at 12:34

1 Answers1

0

First of all JavaScript code does not run in parallel. The most we can say is that it executes asynchronously, i.e. it gets executed by the engine while monitoring its job queues. The "only" thing that might execute in parallel is lower-level, non-JavaScript logic, such as provided by some APIs that make asynchronous HTTP requests.

Secondly, whether an asynchronous operation starts while another is still underway, is not determined by the use of Promise.all, Promise.allSettled, for await ... of, ...etc, but by whether or not all involved promises are created immediately or not. That is part of the code that is not orchestrated by any of the mentioned constructs.

So surely you can use async and await keywords to achieve that asynchronous requests are made without waiting that a previous one has completed.

For instance:

const recordInsertErrors = [];
const promises = jsonArray.map(async (eachPositionReport) => {
    let value;
    try {
        value = await PositionReport.query().insert(eachPositionReport);
    } catch(err) {
        value = {
            vessel_ownership_id: eachPositionReport.vessel_ownership_id, 
            error: err.nativeError
        };
    }
    return value;
});
// All promises will now fulfill, as errors are converted to 
// fulfillments with an error property
(async () => {
    for (const promise of promises) {
        const value = await promise;
        if (value.error) recordInsertErrors.push(value);
        console.log(value);
    }
})();

The for loop with await expressions will not delay the moment at which all promises have resolved. It will potentially report sooner on some results than Promise.allSettled, as the latter is designed to first wait until all promises have settled, and only then resolve its own promise.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • 1
    Please don't use `for await` loops on things that are not asynchronous iterators. Sure, here you specifically made sure that none of the promises reject, but it's still not a good practice. – Bergi Jul 24 '22 at 12:36
  • 1
    Yes, good remark on asynchronous iterators. Replaced it. – trincot Jul 24 '22 at 12:39