skip to Main Content

I have a object I am iterating through and making an axios call per iteration. The following two bits of code are what I have attempted. In one I am using an async function, and using await — In the other, I am using a promises array and using Promise.all(promises) to iterate. They both have the same outcome .. The axios call is sending out 1,000 plus calls all at once, and not "waiting" or "pausing". What am I not seeing?

This is my async version.

function importProjects() {
    Object.keys(importFiles).map(async function (key) {
        await api.post(apiUrl() + "api/v2/addPin/",
            {pin: importFiles[key]})
            .then(response => {
                console.log(response.data);
        });
    });
}

This is my Promise version.

function importProjects() {
   let promises = [];
   Object.keys(importFiles).map(function (key) {
       promises.push(
           api.post(apiUrl() + "api/v2/addPin/", {
               pin: importFiles[key]
           })
       );
   });
   Promise.all(promises)
       .then(response =>
           console.log(response.data)
       );
}

Why to both versions send all my requests simultaneously?

2

Answers


  1. In the first case, .map() is iterating over all of the keys in the object. The result of that iteration is to invoke that callback to .map() on every element, and invoking the callback performs the AJAX operation. Internally that callback may be fully prepared to await, but nothing is awaiting the callback itself.

    In the second case, Promise.all awaits all of the promises, not each individual one in turn.

    Take a step back…

    If the goal is to iterate over a collection and, one at a time, await an operation then why not just use a simple loop? Nesting callbacks is just over-complicating things.

    async function importProjects() {
      const keys = Object.keys(importFiles);
      for (const key of keys) {
        const response = await api.post(apiUrl() + "api/v2/addPin/", {pin: importFiles[key]});
        console.log(response.data);
      }
    }
    
    Login or Signup to reply.
  2. In your async version, you are using await inside the map function, but the map function itself doesn’t wait for the promises to resolve. It just iterates through the array and creates an array of promises. So, all the requests are still being sent simultaneously.
    In your Promise version, you are using Promise.all(), which is designed to wait for all the promises in the array to resolve or reject. However, it doesn’t control the order of execution or add any delay between the requests. So, all the requests are sent simultaneously in this case as well.
    To achieve the desired behavior of waiting for each request to complete before sending the next one, you can use a for loop with an async function. Here’s an example:

    async function importProjects() {
    const keys = Object.keys(importFiles);
    for (const key of keys) {
        try {
            const response = await api.post(apiUrl() + "api/v2/addPin/", {
                pin: importFiles[key]
            });
            console.log(response.data);
        } catch (error) {
            console.error('Error:', error);
        }
    }
    

    }

    In this implementation, we use an async function and a for loop to iterate through the keys. The await keyword ensures that each request is completed before moving on to the next iteration. This way, you can control the order of execution and ensure that requests are not sent simultaneously.

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