Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Will error message be overwritten by concurrent validations? #242

Closed
ivawzh opened this issue Jul 21, 2016 · 3 comments
Closed

Will error message be overwritten by concurrent validations? #242

ivawzh opened this issue Jul 21, 2016 · 3 comments
Labels

Comments

@ivawzh
Copy link

ivawzh commented Jul 21, 2016

Hi, I was reading the README, the following line interests me:

Please note: every time validation function or ajv.validate are called errors property is overwritten. You need to copy errors array reference to another variable if you want to use it later (e.g., in the callback). See Validation errors

For example,

const validate = ajv.compile(customerSchema)

function checkCustomer(id) {
  return promiseFetch(id).then(customer => {
    if (!validate(customer)) {
      console.log(`Customer ${id} has errors: ${validate.errors}`)
    }
  })
}

[id1, id2, id3, ...].forEach(id => {
  checkCustomer(id)
})

Am I right that this code has a risk of having a wrong id-error mapping in Customer ${id} has errors: ${validate.errors} output?

Do I have to create and compile a new ajv insance inside each promise to ensure that my error messages won't be overwritten?

@epoberezkin
Copy link
Member

JavaScript is single threaded and the validation itself in your case is synchronous for each ID.
So there is no such risk.
If, for example, you wan't to collect all errors from all customers you can:

const validate = ajv.compile(customerSchema)

function checkCustomer(id) {
  return promiseFetch(id).then(customer => {
    validate(customer);
    return { id: id, errors: validate.errors };
  })
}

Promise.all([id1, id2, id3, ...].map(id => checkCustomer(id) ))
.then(results => console.log(results));

It will be mapped correctly.

If the schema itself is asynchronous then errors are not returned as the property of validation function but as the property of error object that the promise rejects with.

@epoberezkin
Copy link
Member

epoberezkin commented Jul 21, 2016

In relation to the comment in readme, it means that if you tried to use the same errors in a different execution block they could be errors from the different validation.

For example this code has this problem:

promiseFetch(id)
.then(customer => ({ id: customer.id, valid: validate(customer) }))
.then(result => {
    if (!result.valid) console.log(`Customer ${id} has errors: ${validate.errors}`);
});

But the code below will always work as expected, because errors are used in the same execution block before they can be overwritten:

promiseFetch(id)
.then(customer => {
  var valid = validate(customer);
  return { id: customer.id, valid: valid, errors: validate.errors };
})
.then(result => {
    if (!result.valid) console.log(`Customer ${id} has errors: ${result.errors}`);
});

@ivawzh
Copy link
Author

ivawzh commented Jul 24, 2016

Very well explained. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

3 participants
@epoberezkin @ivawzh and others