简体   繁体   中英

Node.js for loop with callbacks with synchronous execution afterwards

I am having a case of in Nodejs where there is a for loop with callback functions. A loop is called on an array, and for each value an update opearation is called with query and that value is replaced by the result of the query.

The structure is something like this:

console.log(body);

for (var i = 0; i < body.length; i++) {
    console.log(body[i]);
    QueryManager.query(lookup_query, [body[i]], function (err, query_result) {
        if (err) {
            console.log('Query failed', err);
            return;
        }

        query_result = JSON.parse(query_result);

        if(query_result.matrics.resultCount == 1)
            body[i] = query_result.results[0].id;

        console.log("Array value replaced for position:" + i);
    });
}

console.log("Array updated!");

The for loop can be completed with the async execution and then it should wait for all the callbacks to be completed. So the next statements should be in sync after the array is updated fully.

So console outputs for tracking loops should be like in this order:

["1","2","3","4","5"]
Array value replaced for position:0
Array value replaced for position:1
Array value replaced for position:3
Array value replaced for position:2
Array value replaced for position:4
Array updated!

Except the first and the last output, in between outputs can be in any order.

How can I achieve this?

EDIT: The whole thing is inside the http server request. So the array I am getting is from the user's POST. Mapping each value to the actual value from based on the key provided in the array. After all the values replaced in the array from its key to value, I need to prepare some external data based on that values. And then sending that data back to user in the response of that request.

So this should not block the request thread until the whole request is finished and response is send. It should be ready to listen for the new request.

Use async.forEachLimit with limit=1.

Example :

var tempArray = [1, 2, 3, 4, 5];

async.forEachLimit(tempArray, 1, function(no, callback) {
    console.log("Current number : " + no);
    callback();
}, function(error){
    callback(error);
});

This code will print as follow:

Current number : 1

Current number : 2

Current number : 3

Current number : 4

Current number : 5

Basically Promise.all waits for all promises in a collection to resolve and then will it's self resolve calling the .then() :

console.log(body);

var promiseCollection = [];
for (var i = 0; i < body.length; i++) {
    console.log(body[i]);
    promiseCollection.push(new Promise(function (resolve, reject) {
      QueryManager.query(lookup_query, [body[i]], function (err, query_result) {
          if (err) {
              console.log('Query failed', err);
              reject(weFailedAndCanReturnWhy);
              return;
          }

          query_result = JSON.parse(query_result);

          if(query_result.matrics.resultCount == 1)
              body[i] = query_result.results[0].id;

          console.log("Array value replaced for position:" + i);
          resolve(canReturnStuffHere);
      })})
    );
}

Promise.all(promiseCollection)
  .then(function(){
    console.log("Array updated!");
  });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM