1

Ok I have a JS method that uses Lodash and mongoose to find docs in a Mongoose collection. This looks fine, but it that appears to not finish the callback function before moving on to the next doc to look for. Below is my function:

importParts: function(participants, event_id, done){
    _.forEach(participants, function (participant) {
    var race = {event_id: event_id, chip_number_64: participant.chip_number_64};
        Runner.findOne({contact_id: participant.contact_id}, function (err, doc) {
            if (err) {
                logger.error('CANNOT FIND AND UPDATE RUNNER BECAUSE OF: ', err);
                done(err);
            }
            logger.info("IN FINDONE");
            if (doc === null) {
                logger.info("IN FINDONE1");
                participant.races = [race];
                Runner.create(participant, function (err, row, rowsAffected) {
                    if (err) {
                        logger.error('FAILED TO IMPORT PARTICIPANT: ', doc);
                        logger.error(err);
                        done(err);
                    }
                    logger.info("IN FINDONE2");
                });
             }
          });
       };
    done(null);
}  

For some reason the above code does not honor the callback function and appears to asynchronously return back to the main method that is calling this one. It's as if the callback is not being honored till after a set amount of time or something is happening asynchronously that shouldn't because I have everything wrapped in callbacks. So I am just trying to find out why the callback isn't completing when the query is executed? Also, this still happens even without the forEach iteration included in above code.

laggingreflex
  • 32,948
  • 35
  • 141
  • 196
britztopher
  • 1,214
  • 2
  • 16
  • 26
  • The calls to `findOne()` and `create()` are asynchronous. Query is executed and when a response is ready, callback is called. The problem with this code is that `done(null)` is called before those asynchronous functions could finish the execution. You should call `done()` in the callback, but then it would break the `forEach()` loop. You need to refactor this code somehow. – Gergo Erdosi May 21 '14 at 17:31
  • @Gergo Erdosi - yeah, sorry about the `done()` its actually is after the loop, however, i have an extra parenthesis on the foreach block. Editing it now. Does `find` do the same asynchronous behaviour? – britztopher May 21 '14 at 17:55
  • 1
    That's the problem, `done(null)` is after the loop. Currently the execution is: 1. `findOne()`, 2. `done(null)`, 3. callback of `findOne()`. When `findOne()` is called, execution of this script continues, `done(null)` is not waiting for the callback to be finished. – Gergo Erdosi May 21 '14 at 17:59
  • @GergoErdosi - looks like I need to just make this two http calls, or is there someway I can wait till mongoose callbacks finish before continuing? – britztopher May 21 '14 at 19:00
  • You could use the async module. Here is an example which is very similar to your case: http://stackoverflow.com/a/10552398 – Gergo Erdosi May 21 '14 at 19:05
  • 1
    It works for one document, but breaks the foreach, because `done()` is called as soon as the first callback is executed, it won't wait for the other callbacks in the loop. – Gergo Erdosi May 21 '14 at 19:14

0 Answers0