Zstudent
Zstudent

Reputation: 13

nodejs async control flow with loop

What is the problem with this NodeJS code?

I have the following NodeJS snipt.

Profile.findOne(profileId, cb) //is sync function


function getProfiles(users, cb) {
  var results = [];
  var n = users.length;
  users.forEach(function(user, i) {
    Profile.findOne(user.profileId, function(err, prf) {
      if (err) {
        return cb(err, null);
      }
      console.log(prf);
      console.log(user.profileId);
      results.push(prf);
      if (i + 1 == n) {
        console.log('looping done');
        return cb(null, results);
      }
    });
  });
}

// some where 
var userslist = [{
  name: 'ab',
  profileId: 'daf242'
}, {
  name: 'cd',
  profileId: 'hg535h'
}, {
  name: 'ef',
  profileId: 'cvxv445'
}];
getProfiles(userslist, function(err, data) {
  if (err) {
    //do this 
  } else {
    //do that
  }
});

The problem is the results are array of only profiles for the first profileId. like

 [
      {username:'ab',avatarUrl:'abcd.png'}
      {username:'ab',avatarUrl:'abcd.png'},
      {username:'ab',avatarUrl:'abcd.png'}
    ]

but I am expecting array of differnet profiles.

what am I missing?

Upvotes: 0

Views: 337

Answers (2)

Aikon Mogwai
Aikon Mogwai

Reputation: 5225

Use async or promises

var async = require('async');
...
async.map(users, Profile.findOne, function(err, results) {
    if (err)
        return ...// process errors;

    userlist = results; 
})

Upvotes: 0

MrWillihog
MrWillihog

Reputation: 2646

You're mixing synchronous and asynchronous code here. Your forEach loop is running synchronously, but the Profile.findOne method is asynchronous. It then calls the callback passed into the initial function. You should look at using async for an asynchronous for loop.

However, there are many things in your question that suggest you haven't fully grasped the asynchronous nature of Node.js yet. Try reading up on the topic, such as callback hell.

Upvotes: 1

Related Questions