1

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.

rohit garg
  • 283
  • 3
  • 13

2 Answers2

1

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
thammada.ts
  • 5,065
  • 2
  • 22
  • 33
0

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

Art
  • 431
  • 4
  • 12