Search code examples
javascriptnode.jsasynchronouspromisees6-promise

How to replace Async/Await with Promise.AllSettled in a nested loop?


I currently have the below code pulling data from an API and parsing it into my database. It takes up to 5 minutes since there can be up to 50 meets in a day, each with a dozen or so seperate events and each event has up to 20 runners. Think of it like an athletics meet. Sometimes this script is inserting 10,000 rows.

// Create Meetings
for (const meeting of meetingList) {
  const newMeeting = await createMeeting(meeting);

  // Create/Update Events
  for (const event of meeting.events) {
    await createEvent(event, newMeeting.id);

    // Create/Update Competitors
    for (const competitor of event.competitors) {
      await createCompetitor(competitor);
      await createRacingEventCompetitor(competitor, event.id);
    }
  }
}

Previously, I've used Promise.allSettled() as a nice way to make requests in parallel, saving significant time. How do I do the same when you have nested loops like in my example?


Solution

  • Simply create an array to hold the promises, called promises for example

    Then push each request to that array instead of awaiting it

    And await Promise.allSettled(promises)

    Note: since newMeeting is required for the inner requests, you still need to await that ... though, there is a way you can avoid that too

    But, this is a start

    const promises = [];
    for (const meeting of meetingList) {
      const newMeeting = await createMeeting(meeting);
    
      for (const event of meeting.events) {
        promises.push(createEvent(event, newMeeting.id));
    
        for (const competitor of event.competitors) {
          promises.push(createCompetitor(competitor));
          promises.push(createRacingEventCompetitor(competitor, event.id));
        }
      }
    }
    await Promise.allSettled(promises);
    

    Not sure this is the BEST way to make everything parallel, but it is one way

    const promises = [];
    for (const meeting of meetingList) {
        promises.push(
            createMeeting(meeting)
            .then(newMeeting => {
                const innerPromises = [];
                for (const event of meeting.events) {
                    innerPromises.push(createEvent(event, newMeeting.id));
    
                    for (const competitor of event.competitors) {
                        innerPromises.push(createCompetitor(competitor));
                        innerPromises.push(createRacingEventCompetitor(competitor, event.id));
                    }
                }
                return Promise.allSettled(innerPromises);
            })
        );
    }
    await Promise.allSettled(promises);