Search code examples
node.jsmongoosepromisees6-promise

Will a Mongoose queries `then` call occur after any passed in callback completes?


I realize that the standard practice for promises in Mongoose is to use exec(), but the following works (or at least appears to) and I want to understand the flow. I'm not against using exec, I'm just exploring this a bit to learn.

In the following Mongoose operation:

let id:string;

SomeDocument.remove({}, (err) => { //clears collection
  someDoc = new SomeDocument(data); //creates a new doc for the collection. Id is created here from what I understand.
  someDoc.save( (err, result) => { doSomething(); });//doSomething gets called sometime in the future.
  id = someDoc._id.toString();
}).then( (result) => {doSomethingElse(id)});//This works - but will doSomethingElse always be called after the first annonymous callback completes?

I get that doSomething() will just get called at some future point - no problem. The question is, will the first callback to the remove call complete prior to doSomethingElse in the then call being called. It seems to be, in that the id is correctly populated in doSomethingElse, but I want to make sure that isn't just a fluke of timing - i.e. I want to know if I can rely on that callback completing prior to the then. I'm using standard ES6 promises (NodeJS.Global.Promise).

The alternative is that maybe then is called after the remove operation completes, but prior to the callback completing (doesn't seem to - but I want to confirm).

Set me straight if I'm explaining this incorrectly.


Solution

  • Yes, as @JaromandaX explained in the comments the order of callbacks is deterministic.

    However, it's still bad code, and you should not rely on this behaviour. If you are using promises, don't pass a callback to remove at all; only pass callbacks to then!

    SomeDocument.remove({})
    .then(() => {
      const someDoc = new SomeDocument(data);
      someDoc.save().then(doSomething); // doSomething will get called in the future.
      return someDoc._id.toString();
    //^^^^^^
    })
    .then(doSomethingElse); // doSomethingElse will get passed the id
    

    doSomethingElse will get called with the result of the previous callback, which is guaranteed to have been completed for that.