5abre
5abre

Reputation: 51

Run through an array making post requests in an asynchronous manner - Javascript

I am currently trying to make multiple post requests to another page to run functions server side. Because these requests are part of an API call the response times will differ from call to call. So Im trying to run the calls from an array where calls will wait for a response from a function before firing the next request. Currently the calls are all being done at the same time because Im using a forEach loop.

function update() {

    ints.forEach(value => {
        call(value['int']);
    });

    location.reload();
}

function call(value) {
    $.post('PATH TO API CALL'
    ).success(function (resp) {
        $.post('PATH TO FUNCTION'
        ).success(function (resp) {
            // function returns true when completed
        });
    });
}

I would like function "update" to run through function "call" waiting for the response from function "call" that it has completed. Any help would be greatly appreciated.

Upvotes: 0

Views: 62

Answers (2)

mwilson
mwilson

Reputation: 12950

The answer provided by @CertainPerformance certainly works. However, here is how I would do it.

Instead of running a for loop and executing each individual request in a waterfall manner, I would build up an array of promises and then execute them at once with Promise.all. If you do in fact need the promises to run in a waterfall manner (the response from the previous value is required for the next call), then Promise.all probably isn't the best thing to use. In all other cases, I would use it instead.

// Some method that is actually running the request and returning the response
async function executeHttpRequest(id) {
	const response = await fetch(`https://reqres.in/api/users/${id}`);
  return response.json();
}

// Just a quick way to build up an array of promises.
async function callThisManyThings(num) {
  const promises = Array(num).fill(null).map( async (x, i) => executeHttpRequest(i) );
  const results = await Promise.all(promises);
  console.log(results);
}

callThisManyThings(10);

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370979

Easiest tweak would be to make both functions async, so that you can await each call in a for loop (and have call also await each .post):

async function update() {
  for (let i = 0; i < ints.length i++) {
    // the array will be iterated through serially,
    // waiting for the previous call to complete before sending out another
    await call(ints[i]);
  }
  // the next line will only run once all iterations have finished:
  location.reload();    
}

async function call(value) {
  const resp1 = await $.post('PATH TO API CALL' ...);
  // do stuff with resp1, if needed
  const resp2 = await $.post('PATH TO FUNCTION', ...)
  // do stuff with resp2, if needed
}

Also make sure to .catch in the consumer of update to handle any errors that may be thrown.

Upvotes: 2

Related Questions