0

I've come across a situation where I have an asynchronous function inside of a for loop. I've done my prerequisite searching and now know that forEach() or map() might be the solution I need. But all of the examples I see just console.log() the result of each async function. How would it work to have to set the results of each async function into a variable, and then only return the variable?

Here's some slimmed down code of what I'm doing: (this is all in node, by the way)

var clients={
    "102323":{stuff about this client},
    "242341":{stuff about that client}
};
var messages={};
for (var id_client in clients) {
    mysql.query("SELECT * FROM messages WHERE id_client='"+id_client+"' ORDER BY date", function(err, rows) {
        if (typeof rows !== 'undefined') messages[id_client]=rows;
    });
}
//do other stuff with messages variable

With this, messages predictably is null. Which I understand.

But even when I transition this to using map() instead of for(), like this...

var messages={};
Object.keys(clients).map(function(id_client){
    mysql.query("SELECT * FROM messages WHERE id_client='"+id_client+"' ORDER BY date", function(err, rows) {
        if (typeof rows !== 'undefined') messages[id_client]=rows;
    });
});

...messages ends up being null.

Finally, just want to note that I do know how to wrap mysql.query() into another function with a callback and all that to get around the whole asynchronous thing. I just don't know how that all works if being iterated on inside of a loop.

4
  • 1
    There is no difference in your map call vs your for loop - FYI. Commented Aug 24, 2016 at 12:42
  • @tymeJV - there is a difference ... id_client will be "correct" for each iteration of .map ... in the for loop, it would be the last client every time Commented Aug 24, 2016 at 12:54
  • the similarity is WHEN messages will be populated - i.e. well after the next line of code (not shown in either snippet) Commented Aug 24, 2016 at 12:55
  • Also, this way of inserting variables inside your queries is highly discouraged, see github.com/mysqljs/mysql#escaping-query-values for more information, i'd personally go with mysql.query("SELECT * FROM messages WHERE id_client = ? ORDER BY date", ['id_client'], function(err, rows) { Commented Aug 24, 2016 at 12:59

3 Answers 3

3

You can use Promise.

var messages = {};

Promise.all(Object.keys(clients).map((id_client) => {
  return new Promise((resolve, reject) => {
    mysql.query("SELECT * FROM messages WHERE id_client='" + id_client + "' ORDER BY date", function(err, rows) {
      if (typeof rows !== 'undefined') {
        messages[id_client] = rows;
        resolve(rows);
      }
    });
  });
})).then(results => {
  console.log(messages);
});

Sign up to request clarification or add additional context in comments.

Comments

1

Here is a pure JavaScript version:

var clients={
    "102323":{stuff about this client},
    "242341":{stuff about that client}
};
var messages={};
var cnt = 2;

function done() {
    console.log(messages);
}

mysql.query("SELECT * FROM messages WHERE id_client='"+id_client+"' ORDER BY date", function(err, rows) {
    cnt--;
    if (typeof rows !== 'undefined') messages[id_client]=rows;
    if(!cnt) done();
});

Comments

0

I presume you are console.log()ing just after map. But map didn't finished yet, since it's callback is asynchonous.

You can use async to get a asynchnous version of map, which will work:

'use strict';
let async = require('async'),
    messages = {};

async.map(Object.keys(clients), (id_client) => {
    mysql.query("SELECT * FROM messages WHERE id_client='"+id_client+"' ORDER BY date", (error, rows) => {
        if (typeof rows !== 'undefined') {
            messages[id_client]=rows;
        }
        callback(error);
    });
}, (error) => {
    if(error) {
        console.log(error);
    }
    console.log(messages);
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.