I’m new to node and javascript and have been banging my head on the following. I’ve created an object as follows:
var Subscriber = {
'userID': String,
'email': String,
'name': String,
'stage': String,
'poster': Boolean,
'canEmail': Boolean,
'stage': String, }
I have a function where I query mongodb, and loop through the results, attempting to load an array of subscribers, which I’ve declared as:
var s = Subscriber;
var subscribers = [];
The loop looks like this:
//load array of users that are subscribed to the group
async.forEach(g.subscribers, function(item, callback) {
//load user document for this user
User.findOne({ _id: item}, function(err, u) {
if(!err && u) {
//var s = new Subscriber();
console.log('Sub load, found user %s, building array item', u.email);
console.log('Subs @ loop start');
console.log(util.inspect(subscribers));
console.log('Heres foo: ' + util.inspect(foo));
s.userID = u._id;
s.email = u.email;
s.name = u.firstName + ' ' + u.lastName;
s.stage = u.stage;
s.poster = false; //we're just loading subscribers at this point'
if(s.stage != 'new') s.canEmail = true;
//push new subscriber onto the array
console.log('Pushing ' + util.inspect(s));
subscribers.push(s);
console.log('At end ' + util.inspect(subscribers));
foo.push(s.email);
console.log('Heres foo now: ' + util.inspect(foo));
callback(null, item);
}
After each call to subscribers.push(s), the array has the correct number of elements, but all elements match the last values for s, like this (with two different users being pulled from the DB):
[ { userID: 4fc53a71163006ed0f000002,
email: 'test@test.com',
name: 'undefined undefined',
stage: 'new',
poster: false,
canEmail: true },
{ userID: 4fc53a71163006ed0f000002,
email: 'test@test.com',
name: 'undefined undefined',
stage: 'new',
poster: false,
canEmail: true } ]
Pushing a single element of s rather than the whole object seems to be fine. I added the “foo” array as a test, and it works fine:
Heres foo now: [ 'email1@foo.com', 'test@test.com' ]
What is going on here?!?!??!
The problem is not with the
pushmethod of theArray.prototypebut with your bindings.You are modifying the same
sobject in every iteration in yourasync.foreachblock which is actually the same Object as the previously definedSubscriber.First you should move the declaration of the
svariable to the foreach block.And also if you want to create an object with default values, it should be a
function, which returns a new object:And then you can instantiate a
Subscriberobject like this:See this answer or Closures on MDN for more explanation.