JavaScript: Asynchronous method in while loop JavaScript: Asynchronous method in while loop javascript javascript

JavaScript: Asynchronous method in while loop


edit: see the bottom, there is the real answer.

I encourage you yo use the Promise API. Your problem can be solved using a Promise.all call:

let promises = [];while(something){    promises.push(new Promise((r, j) => {        YourAsyncCall(() => r());    });}//Then this returns a promise that will resolve when ALL are so.Promise.all(promises).then(() => {    //All operations done});

The syntax is in es6, here is the es5 equivalent (Promise API may be included externally):

var promises = [];while(something){    promises.push(new Promise(function(r, j){        YourAsyncCall(function(){ r(); });    });}//Then this returns a promise that will resolve when ALL are so.Promise.all(promises).then(function(){    //All operations done});

You can also make your api call return the promise and push it directly to the promise array.

If you don't want to edit the api_call_method you can always wrap your code in a new promise and call the method resolve when it finishes.

edit: I have seen now the point of your code, sorry. I've just realized that Promise.all will not solve the problem.

You shall put what you posted (excluding the while loop and the control value) inside a function, and depending on the condition calling it again.

Then, all can be wraped inside a promise in order to make the external code aware of this asynchronous execution. I'll post some sample code later with my PC.

So the good answer

You can use a promise to control the flow of your application and use recursion instead of the while loop:

function asyncOp(resolve, reject) {    //If you're using NodeJS you can use Es6 syntax:    async_api_call("method.name", {}, (result) => {      if(result.error()) {          console.error(result.error());          reject(result.error()); //You can reject the promise, this is optional.      } else {          //If your operation succeeds, resolve the promise and don't call again.          if (result.data().length === 0) {              asyncOp(resolve); //Try again          } else {              resolve(result); //Resolve the promise, pass the result.          }      }   });}new Promise((r, j) => {    asyncOp(r, j);}).then((result) => {    //This will call if your algorithm succeeds!});/* * Please note that "(...) => {}" equivals to "function(...){}" */


If you don't want to use recursion you can change your while loop into a for of loop and use a generator function for maintaining done state. Here's a simple example where the for of loop will wait for the async function until we've had 5 iterations and then done is flipped to true. You should be able to update this concept to set your done variable to true when your webservice calls have buffered all of your data rows.

let done = false;let count = 0;const whileGenerator = function* () {    while (!done) {        yield count;    }};const asyncFunction = async function(){    await new Promise(resolve => { setTimeout(resolve); });};const main = new Promise(async (resolve)=>{    for (let i of whileGenerator()){       console.log(i);       await asyncFunction();       count++;       if (count === 5){           done = true;       }    }    resolve();});main.then(()=>{    console.log('all done!');});


Also you may try recursion solution.

function asyncCall(cb) {// Some async operation}function responseHandler(result) {    if (result.error()) {        console.error(result.error());    } else if(result.data() && result.data().length) {        asyncCall(responseHandler);    }}asyncCall(responseHandler);