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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.