jj-aa
jj-aa

Reputation: 1039

Inserting multiple documents with mongodb in a post request

Inserting multiple documents with mongodb in the same request I'm getting undefined value.

.post(function (req, res) {
    ...
    Item.create(data)
    .then(function (item) {

        var modelOtherItem;            

        OtherItem.create({
            ...
        }).then(function (otherItem){
            modelOtherItem = otherItem; 
            modelOtherItem; // here I get the expected value       
        });

        res.status(201);

        res.json({
            item: item, // has a value
            otherItem: modelOtherItem // -> is undefined
        });
    });

Upvotes: 2

Views: 346

Answers (1)

nem035
nem035

Reputation: 35501

Promises return immediately but their then callbacks execute asynchronously. That means you are accessing modelOtherItem before it's assigned a value. The easiest fix would be to add your code inside the then callback (you can also get rid of the modelOtherItem variable):

post(function (req, res) {
  // ...
  Item.create(data)
  .then(function (item) {

    OtherItem.create({
        // ...
    }).then(function (otherItem){            

        // add code here
        res.status(201);

        res.json({
          item: item, // has a value
          otherItem: otherItem // also has value
        });     
    }); 
});

One thing to note that you can create all of your items with one call by passing an array to Model.collection.insert(array... or, if using Mongoose, Model.create(array...


Alternative solution

If you models can be created independently of one another (meaning that creation of any item doesn't depend on any other item), you can use the Promise.all method that takes an array of promises and resolves once all of the promises in that array resolve as well:

post(function (req, res) {
  // ...

  // create an array that will hold item creation promises
  let promises = [];

  // add the promise that creates the item
  promises.push(Item.create(...));

  // add the promise that creates the other item
  promises.push(OtherItem.create(...));

  Promise.all(promises)
  .then(function(results) { // this function is called once all promises in the array `promises` resolve
    // results contains the resolved data from each promises in the array
    // in the order of the promises

    var item = results[0];
    var otherItem = results[1];

    // OR you can use ES6 `let` declaration with 
    // destructuring to achieve the same as above
    // in a cleaner way:
    // let [item, otherItem] = results;

    res.status(201);

    res.json({
      item: item,
      otherItem: otherItem
    });  

    // in ES6, if both the object property name and the variable name are the same
    // you can just specify the name once and achieve the same effect as above
    // with less code:
    /*
    res.json({
      item,
      otherItem
    });  
    */
  });
});

Upvotes: 4

Related Questions