skip to Main Content

I’m struggling to come up with a dynamic solution, I have an array of items, I need to send a POST request for each item in the array, however I do not want to send the next request until the previous promise is resolved.

So dynamically chaining .then() methods, i.e. send the first POST request, wait for that to get resolved before sending the second POST request, wait for second to get resolved before sending third POST request, etc.

Here is my static code, where I send a POST request for the first item in the commandPayloads array, then send a POST request for the second item after the first is resolved.

const commandPayloads = await createInitialCommands(copiedCommands);

  commandPOSTFetch(commandPayloads[0], newResponseSetID).then(() => {
    commandPOSTFetch(commandPayloads[1], newResponseSetID);
  });

const commandPOSTFetch = async (command, newResponseSetID) => {
  const res = await fetch(`https://${someWebSite}/${appID}//${interactionID}/response/${newResponseSetID}/commands.json`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(command),
    }
  );
  const data = await res.json();
  return data;
};

the example above is working if there are 2 items in the array, but what if I have more than 2?

How can I make this logic dynamic, based off the number of items in the array, so the POST requests are send in sequential order, only after the previous is resolved?

*Update with For Loop

  commandPayloads.forEach(async (command, i) => {
    const data = await commandPOSTFetch(command, newResponseSetID)
    console.log('in loop', data);
  });

2

Answers


  1. To achieve dynamic chaining of POST requests based on the number of items in the commandPayloads array, you can use a recursive approach with Promises. Here’s an example of how you can do it:

    
        const commandPayloads = await createInitialCommands(copiedCommands);
        
        // Function to send a POST request and return a Promise
        const commandPOSTFetch = async (command, newResponseSetID) => {
          const res = await fetch(`https://${someWebSite}/${appID}//${interactionID}/response/${newResponseSetID}/commands.json`, {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify(command),
          });
          const data = await res.json();
          return data;
        };
        
        // Function to chain the POST requests sequentially
        const sendSequentialRequests = (payloads, index = 0) => {
          if (index < payloads.length) {
            return commandPOSTFetch(payloads[index], newResponseSetID)
              .then(() => sendSequentialRequests(payloads, index + 1));
          } else {
            // All requests have been sent
            return Promise.resolve();
          }
        };
        
        // Start the chain of requests
        sendSequentialRequests(commandPayloads)
          .then(() => {
            // All requests are completed
            console.log("All POST requests have been sent.");
          })
          .catch((error) => {
            console.error("Error:", error);
          });
    
    

    This code defines a sendSequentialRequests function that sends POST requests one by one in a sequential manner using Promises. It starts by sending the first request, and when that request is resolved, it calls itself recursively with the next index until all requests are sent. The .then() and .catch() at the end handle the completion or error of the entire sequence of requests.

    Login or Signup to reply.
  2. Just for the record, it turns out that the simplest thing to do (and, really, given the "wait until one thing finishes before doing the next thing" requirement, almost the only way to do it) is to use a good old-fashioned for loop:

    let listOfThings = whatever;
    for (let i = 0; i < listOfThings.length; ++i)
        const asyncResult = await somefunc(listOfThings[i]);
        // ...
    }
    

    The reason a for loop is better in this case than .forEach() or even .map() is that in an async function, those await expressions really will wait until each Promise is satisfied before proceeding to the next iteration. (Obviously in real code you’d deal with exceptions etc.)

    Sometimes you don’t need to sequence things. In such cases, using .map() to collect a bunch of Promise objects that can then used with await Promise.all(collected) is great. But when you do want a strict one-before-the-other sequence, a plain loop is the best bet.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search