3

Given an array of Strings that represent item ids, I want to iterate through the strings, pull the item object from my database, and add the item object to an array, that lies outside the scope of the callback from my database.

function getItemObjects(items, callback) {
  let returnItems = [];
  items.forEach((i) => {
    Item.getItemById(i, (err, item) => {
      if (err) {
        console.log(err);
        return;
      } else {
        returnItems.push(item);
      }
    });
  });
  callback(returnItems);
}

Item.getItemById() is a function within my Item model that gets the object from a mongo database. How can I populate an array that's outside the scope of that callback function?

As it stands when I get the callback value from the getItemObjects() function the value is just []. However if I log the value of it within the for loop it is properly populated.

Darren
  • 1,774
  • 4
  • 21
  • 32
  • 1
    What do you get in `returnItems` just before `callback(returnItems);` is executed? – Ankit Agarwal Dec 02 '17 at 07:08
  • It just returns an empty array. Anytime I reference it outside the scope of the Item.getItemById() callback function it is empty, it's like it resets when I leave that function. – Darren Dec 02 '17 at 07:09
  • 1
    Using a promise sounds like an idea - I think this question is a dupe of https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call – mplungjan Dec 02 '17 at 07:09

1 Answers1

2

You can use promises to extract the values from the database callback.

try this:

function getItemObjects(items, callback) {
  const itemPromises = items.map((itemId) => {
    return new Promise((resolve, reject) => {
      Item.getItemById(itemId, (err, item) => {
        if (err) {
          reject(err);
        }
        resolve(item);
      });
    });
  });

  Promise.all(itemPromises)
    .then(results => callback(results))
    .catch(error => callback(error));

}

Pay attention here, if any of the items results in an error, then the whole promise (from Promise.all) will fail and the catch block will be executed.

You can find more on Promise.all and Promise.catch

marceloemanoel
  • 385
  • 3
  • 11