floatleft
floatleft

Reputation: 6551

Push to a new array inside a map/promise

Here is a simplified version of my current setup.

When running this code you'll notice that modifying the changes array also manipulates the original referrals array. Is this because I'm pushing to the changes array inside a map function? How can I modify the changes array without modifying the referrals array?

var referrals = [
  {
    id: 1,
    name: 'John',
    change: true
  },
  {
    id: 2,
    name: 'Sally',
    change: false
  },
  {
    id: 3,
    name: 'Kim',
    change: true
  }
];

var changes = [];

var process = referrals.map(function(referral) {
  return new Promise(function(resolve, reject) {
    if (referral.change) {
      changes.push(referral);
    }
    resolve();
  });
});

Promise.all(process).then(function() {
  console.log('referrals before:', referrals);
  changes = changes.map(function(change) {
    change.change_id = change.id;
    delete change.id;
    return change;
  });

  console.log('changes:', changes);
  console.log('referrals after:', referrals);
});

Upvotes: 2

Views: 10138

Answers (2)

floatleft
floatleft

Reputation: 6551

Thanks blex for walking me through what was going on here. Essentially when I was pushing the object to a new array, I was pushing the entire reference and not just a copy. Using Object.assign to clone the object solves my issue.

Here is the entire edit for reference:

var referrals = [
  {
    id: 1,
    name: 'John',
    change: true
  },
  {
    id: 2,
    name: 'Sally',
    change: false
  },
  {
    id: 3,
    name: 'Kim',
    change: true
  }
];

var changes = [];

var process = referrals.map(function(referral) {
  new Promise(function(resolve, reject) {
    if (referral.change) {
      changes.push(Object.assign({}, referral));
    }
    resolve();
  });
});

Promise.all(process).then(function() {
  console.log('referrals before:', referrals);
  changes = changes.map(function(change) {
    change.change_id = change.id;
    delete change.id;
    return change;
  });

  console.log('changes:', changes);
  console.log('referrals after:', referrals);
});

Upvotes: 1

felixmosh
felixmosh

Reputation: 35553

You just need to create a deep copy of the inner objects, you can do it with lodash deepClone, or spread operator.

Something like that:

var referrals = [
{
  id: 1,
  name: 'John',
  change: true
},
{
  id: 2,
  name: 'Sally',
  change: false
},
{
  id: 3,
  name: 'Kim',
  change: true
}
];

var changes = [];

var process = referrals.map(function(referral) {
  return new Promise(function(resolve, reject) {
    if (referral.change) {
      changes.push({...referral}); // You will create a copy here.
    }
    resolve();
  });
});

Promise.all(process).then(function() {
  console.log('referrals before:', referrals);
  changes = changes.map(function(change) {
  change.change_id = change.id;
  delete change.id;
  return change;
});

console.log('changes:', changes);
console.log('referrals after:', referrals);
});

Upvotes: 3

Related Questions