1

I have quite a simple problem, but I can't find an elegant solution to fix this. In the following code, I have two nested calls to a mongo DB. I use Monk to manage my calls. The problem is : the for loop (1) loops before the nested insertion can happen. So the next find (2) instruction does not find the last inserted action.

The call order is 1-2-2-2-3-3-3 (for an actionList of size 3). So all my data is inserted.

My objective is to have the call order 1-2-3-2-3-2-3

Do you have any clue of how to manage such a problem, without making a big find on my database and manage my list server-side ? (Get all data, make myself the search, that is quite horrible to do, insert elements I want, then push it all to the db...)

for (var action of actionList)//(1)
{
    collectionActions.find(//(2)
        {eventid : action.eventid}, 
        function(e,actionsFound)
        {
            if (actionsFound.length == 0)
            {
                collectionActions.insert(action, function(err, result)//(3)
                {
                    console.log("insert action : " + action._id);
                })
            }
        }
    )
}
2

2 Answers 2

2

The native Promise object has an all method that could be leveraged to help.

Assuming find is a compliant promise, the following code would queue up all of the actions in an array through map and which would return a promise for each action that eventually returns messages to the final then for all.

A couple of notes: your code as it stands swallows all of the errors that might occur (I'm not sure that is want you want); this also assumes that insert returns a promise.

Promise.all([
  // Iterate over actionList
  actionList.map(function(action) {
    // returns a promise with a then already attached
    return collectionActions.find({
      eventid: action.eventid
    }).then(function(e, actionsFound) {
      if (actionsFound.length == 0) {
        // returns another promise that will resolve up to outer promises
        return collectionActions.insert(action, function(err, result) {
          // Finally resolve a value for outer promises
          return 'insert action : ' + action._id;
        });
      } else {
        // A different value to resolve with if the above promise
        //  is not required
        return 'some other message for ' + action._id;
      }
    });
  })
]).then(function(results) {
  // Log out all values resolved by promises
  console.log(results);
});

UPDATE: After the clarification of the question it sounds like you just need to chain the promises together rather than run them in parallel.

// Iterate over actionList
actionList.reduce(function(promise, action) {
  // Chain promises together
  return promise.then(function(results) {
    return collectionActions.find({
      eventid: action.eventid
    }).then(function(e, actionsFound) {
      if (actionsFound.length == 0) {
        // returns another promise that will resolve up to outer promises
        return collectionActions.insert(action, function(err, result) {
          // Finally resolve a value for outer promises
          return results.push('insert action : ' + action.sourceName);
        });
      } else {
        // A different value to resolve with if the above promise
        //  is not required
        return results.push('some other message for ' + action.sourceName);
      }
    });
  });
}, Promise.resolve([])).then(function(results) {
  // Log out all values resolved by promises
  console.log(results);
});

Sign up to request clarification or add additional context in comments.

2 Comments

I'm sorry to say that it does not work. My first map has 3 actions with the same event id. The 3 of them are inserted... I updated my question, to be sure that my need is clear.
@strategesim I see. Your original question was a bit unclear about that. I've updated the answer to reflect the change that would be required to work for your restrictions.
0

I finally got my solution, by using a recursive function.

var currentIndex = 0;

var searchAndInsert = function(actionList)
{
    var action = actionList[currentIndex];
    if (typeof actionList[currentIndex] != "undefined")
    {
        collectionActions.find(
            {eventid : action.eventid}, 
            function(e,actions)
            {
                console.log("find ended")

                if (actions.length == 0)
                {
                    collectionActions.insert(action, function(err, result)
                    {
                        console.log("insert action : " + action.sourceName);
                        currentIndex++;
                        if (typeof actionList[currentIndex] != "undefined")
                            searchAndInsert(actionList);
                    })
                }
                else
                {
                    currentIndex++;
                    if (typeof actionList[currentIndex] != "undefined")
                        searchAndInsert(actionList);
                }
            }
        )
    }
};

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.