Reputation: 104
I have a mongoose schema like the following:
const User: Schema = new Schema({
// some other fields
email: {type: String, unique: true, require: true, validate: [myValidator, 'invalid email provided'],
// some more fields
)};
My myValidator uses validatorJS isEmail function to check if a valid email address has been entered and looks like this:
function myValidator(email: String) {
return isEmail(email: String, {require_tld: true, domain_specific_validation: true});
So far all of this works as expected. But now I have the following problem, which might be linked to my limited understanding of Typescript/JaveScript.
I would like to extend myValidator
to check the entered email address against an external API.
So far I've tried something like this:
function myValidator(email: String) {
let isValid = false;
request('https://disposable.debounce.io/?email=' + email, { json: true }, async (err, res, body) => {
if (err) { return console.log(err); }
isValid = body.disposable;
});
if (isValid && !isEmail(email, {require_tld: true, domain_specific_validation: true})) {
return false;
}
But this obviously fails as request is an async operation so isValid
will always be false
So I 'attempted' to make this function an async/await function.
function myValidator(email: String) {
const remoteCheck = function() {
return new Promise(function() {
request('https://disposable.debounce.io/?email=' + email, { json: true }, async (err, res, body) => {
if (err) { return console.log(err); }
return body.disposable;
});
});
};
async function f() {
const isValid = await remoteCheck();
if (isValid === true) {
return false;
} else {
isEmail(email, {require_tld: true, domain_specific_validation: true});
}
}
if(f()) {
return true;
} else {
return false;
}
But this gives me an error, because this function is not assignable to validate. Please note that this is my first attempt on async/await functions. Could somebody point out what I'm missing here?
UPDATE: So after I've spend a whole day now to familiarize myself with the concepts of callbacks and promises I came up with a working solution. I'll provide it as an answer below
Upvotes: 0
Views: 405
Reputation: 104
I checked SO and I couldn't find a solution to this. So if anybody comes across this issue again, I'll provide a working solution for this.
If you want to validate a field against an external data-source, try the following. This validator will check the email-address provided against an API (you can of course use any other API as well) that checks if the address is a DEA and also use ValidatorJS isEmail to check for syntax:
const YourSchema = new Schema({
// your fields
})
SchemaName.path('fieldNameToCheck').validate({
validator: function(value) {
return new Promise(function (resolve, reject) {
request.get('https://disposable.debounce.io/?email=' + value, function (error, response, data) {
if (error) reject(error);
const content = JSON.parse(data);
resolve((content.disposable === 'false' && isEmail(value)))
}
});
}
});
The mistake I made was that I tried to resolve my Promise outside of the callback_function of my request. But the data I want to use is obviously only available inside of it on time.
EDIT:
for the purpose of understanding the API call. The API returns a JSON in the form of {disposable: boolean}
whether the entered email-address belongs to a DEA (disposable Email Address) service
Upvotes: 1