emonigma
emonigma

Reputation: 4416

Mongoose: the isAsync option for custom validators is deprecated

The Stripe Rocket Rides demo uses isAsync in a validator:

// Make sure the email has not been used.
PilotSchema.path('email').validate({
  isAsync: true,
  validator: function(email, callback) {
    const Pilot = mongoose.model('Pilot');
    // Check only when it is a new pilot or when the email has been modified.
    if (this.isNew || this.isModified('email')) {
      Pilot.find({ email: email }).exec(function(err, pilots) {
        callback(!err && pilots.length === 0);
      });
    } else {
      callback(true);
    }
  },
  message: 'This email already exists. Please try to log in instead.',
});

This method throws an error with a reference

DeprecationWarning: Mongoose: the `isAsync` option for custom validators is deprecated. Make your async validators return a promise instead: https://mongoosejs.com/docs/validation.html#async-custom-validators

The MongoDB page quoted has this code:

const userSchema = new Schema({
  name: {
    type: String,
    // You can also make a validator async by returning a promise.
    validate: () => Promise.reject(new Error('Oops!'))
  },
  email: {
    type: String,
    // There are two ways for an promise-based async validator to fail:
    // 1) If the promise rejects, Mongoose assumes the validator failed with the given error.
    // 2) If the promise resolves to `false`, Mongoose assumes the validator failed and creates an error with the given `message`.
    validate: {
      validator: () => Promise.resolve(false),
      message: 'Email validation failed'
    }
  }
});

I am new to NodeJS and I don't see how to adapt the MongoDB code to the Rocket Rides demo. Neither Implicit async custom validators (custom validators that take 2 arguments) are deprecated in mongoose >= 4.9.0 nor Mongoose custom validation for password helped.

How can I verify the uniqueness of email addresses and avoid that error?

Upvotes: 0

Views: 1545

Answers (1)

Nelbren
Nelbren

Reputation: 71

try this, I had the same problem.

To fix it use a separate async function that you call with await.

// Make sure the email has not been used.
PilotSchema.path('email').validate({
    validator: async function(v) {
        return await checkMailDup(v, this);
    },
    message: 'This email already exists. Please try to log in instead.',
});

async function checkMailDup(v, t) {
  const Pilot = mongoose.model('Pilot');
  // Check only when it is a new pilot or when the email has been modified.
  if (t.isNew || t.isModified('email')) {
      try {
        const pilots = await Pilot.find({ email: v });
        return pilots.length === 0;
      } catch (err) {
        return false;
      }
  } else {
      return true;
  }
}

Let me know if it works.

I used the following references:

Cheers!

Upvotes: 3

Related Questions