0

I'm kinda new to NodeJS and I'm trying to use custom async validators for two of the fields. The reason why I'm using an async validator is that a request must be made to the database to check if a record with that id already exists. I implemented two validators (code listed below) - if I use only one of them in the validate.async constraints, each of them work. However, if I use both of them at the same time, an unhandled promise rejection (exact error also below) is thrown and only the first validator's error is returned.

Code: timezoneValidateAsync:

function valAsync(value) {
    return new validate.Promise(async function(resolve, reject) {
      const timezone = await Timezone.findById(value);
      if (!timezone) {
        reject(ValidationErrors.NOSUCHTIMEZONE);
      }
      resolve();
    });
  }

  validate.validators.timezoneValidateAsync = valAsync;

languageValidateAsync:

function valAsync(value) {
    return new validate.Promise(async function(resolve, reject) {
      const language = await Language.findById(value);
      if (!language) {
        reject(ValidationErrors.NOSUCHLANGUAGE);
      }

      resolve();
    });
  }

  validate.validators.languageValidateAsync = valAsync;

Usage in validate.async:

constraints = {
      timezoneId: {
        presence: {
          message: ValidationErrors.TIMEZONEIDEXISTS
        },
        numericality: {
          greaterThan: 0,
          message: ValidationErrors.TIMEZONEIDGREATERTHANZERO
        },
        timezoneValidateAsync: {}
      },
      languageId: {
        presence: {
          message: ValidationErrors.LANGUAGEIDEXISTS
        },
        numericality: {
          greaterThan: 0,
          message: ValidationErrors.LANGUAGEIDGREATERTHANZERO
        },
        languageValidateAsync: {}
      }
    };

validate.async({
        timezoneId: fpreferencesDS.timezoneId,
        languageId: fpreferencesDS.languageId
      }, constraints).then(() => {
        next();
      }, errors => {
        console.log(errors);
        return;
      });

If I comment out the timezoneValidateAsync validator, the language error is returned fine in the errors variable. If I comment out the languageValidateAsync, the timezone error is returned fine. If I leave them both uncommented, the following unhandled promise rejection is thrown:

(node:25280) UnhandledPromiseRejectionWarning: # (node:25280) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:25280) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I guess my mistake is somehow in chaining those promises, but I don't really have idea how to do it (if I'm right at all). I'm open to any suggestions, ideas and pointers.

Veselin Bakov
  • 103
  • 1
  • 11

1 Answers1

1

I found my mistake, it turns out that I shouldn't the promise reject in case of an error. Instead, I should resolve it with the error message. Example (for both of the validators):

if (!timezone) {
   resolve(ValidationErrors.NOSUCHTIMEZONE);
   return;
}

instead of

if (!timezone) {
   reject(ValidationErrors.NOSUCHTIMEZONE);
   return;
}
Veselin Bakov
  • 103
  • 1
  • 11