rohit garg
rohit garg

Reputation: 323

pre save middleware in mongoose

i am first time using pre save middleware and getting a bit confusion in it.

It runs perfectly fine and also my save method is getting executed eventhough i am not calling the next()

case 1

tourSchema.pre('save', function () {
  console.log('first middleware is getting called');
})

But when i do like this when next is declared inside the function params but i don't call the next() it hangs there and the save method is not getting executed

case 2

tourSchema.pre('save', function (next) {
  console.log('first middleware is getting called');
});

But as soon as i call the next() it gets executed

case 3

tourSchema.pre('save', function (next) {
  console.log('first middleware is getting called');
  next()
});

so i only want to know what's the wrong with the second case . In this i have only and only this pre middleware . How defining the next inside the function params can matter, the save method should also be executed in the second case since i don't have any second pre middleware.

Upvotes: 1

Views: 2202

Answers (2)

Art
Art

Reputation: 461

thammada's answer perfectly explains your issue, I just want to add and say you can actually use an async function to escape the obligation to call next()

Pre middleware functions are executed one after another, when each middleware calls next.

`const schema = new Schema(..);
 schema.pre('save', function(next) {
   // do stuff
   next();
 });`

In mongoose 5.x, instead of calling next() manually, you can use a function that returns a promise. In particular, you can use async/await.

schema.pre('save', function() {
  return doStuff().
  then(() => doMoreStuff());
});

Read more about it here

Upvotes: 0

thammada.ts
thammada.ts

Reputation: 5245

mongoose uses kareem library to manage hooks.

kareems makes use of the length property of your hook function to determine whether next is defined as an argument or not.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length

Your first function has no arguments, kareem will assume this is a sync function

const firstFunction = function () {
  console.log('first middleware is getting called');
})
console.log(firstFunction.length) // this will output 0

Your second function has 1 argument, the kareem library will see your function accept next arguments. It will pass a callback and execute it in the next function. Since next is never called, that callback will be never called.

const secondFunction = function (next) {
  console.log('first middleware is getting called');
})
console.log(secondFunction.length) // this will output 1

Upvotes: 1

Related Questions