0

I'm currently working on a form validation that requires a little bit of ajax. With the help of this post, I had each validation fire sequentially.

I now need to break the promise as soon as it sees a false value in the array of validations vs. completing regardless of the true/false values within the array. How could I incorporate this concept based on what I have now?

var validations = [validatePassword, validateName, validateAddress, ...];

$continueButton.on('click', function() {    
  subscribe().then(function() {
   // Do something
  }, function() {
    // Show error
  });
});

function subscribe() {
  var promises = validations.map(function(validation) {
    return validation();
  });

  return Promise.all(promises);
}

function validatePassword() {
  var password = $password.val();
  var format = /^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])[^+&\n]{8,}$/;
  return validateInput(format.test(password), $password);
}

function validateAddress() {
  return new Promise(function (resolve, reject) {
    $.ajax({
      type: 'POST',
      url: '/address/validate',
      data: $form.serialize(),
      dataType: 'json',
      success: function(response) {
        var hasValidAddres = response.Data === 200;

        validateInput(hasValidAddres, $address);

        hasValidAddres ? resolve() : reject();
      }, 
      error: function() {
        // Show error
      }
    });
  });
}

function validateInput(validation, $input) {
  if (validation) {
    $input.removeClass('invalid');
    return true;
  } else {
    markAsInvalid($input);
    // Was originally return false
    return Promise.reject('Example Error');
  }
}

function markAsInvalid($input) {
  $input.addClass('invalid');
}
Community
  • 1
  • 1
Carl Edwards
  • 13,826
  • 11
  • 57
  • 119

2 Answers2

0

According to MDN:

Promise.all fail-fast behaviour

Promise.all is rejected if one of the elements is rejected and Promise.all fails fast: If you have four promises which resolve after a timeout, and one rejects immediately, then Promise.all rejects immediately

So your code should work as is; one a validation fails, Promise.all gives up and returns false immediately.

Community
  • 1
  • 1
DogPawHat
  • 437
  • 3
  • 9
0

You should reject with Error in one of your validators:

function validatePassword() {
  if (invalidPassword) {
    var err = new Error('Invalid passw');
    return Promise.reject(err);
  }
}

In the case of the error in one of validators, in subscribe function then block won't be called, but catch will.

alexmac
  • 19,087
  • 7
  • 58
  • 69
  • When you say, "You should reject with Error in one of your validators", am I only writing `return Promise.reject(err);` in just one of the validation functions in my `validations` array? – Carl Edwards Apr 08 '16 at 15:54
  • To reject promises chain, you should add this code in every validation function and reject with error, when validation fails. – alexmac Apr 08 '16 at 15:57
  • I'm getting `Uncaught (in promise) Error` – Carl Edwards Apr 08 '16 at 16:06
  • Got rid of that error but noticing ever since changing the return value to: `return Promise.reject(err);` nothings happening anymore. Is it because it's expecting either `true` or `false`? – Carl Edwards Apr 08 '16 at 16:14
  • Hmm, first of all I don't know how your validation functions work, you haven't added them in question. You should call `Promise.reject(err)` only if something wrong in your validation func, otherwise you should return nothing (because you don't use validation result in your code). – alexmac Apr 08 '16 at 16:20
  • I'll update my original question to include the how it fully works. One sec. – Carl Edwards Apr 08 '16 at 16:21
  • Okay, updated my question code. Note that that I put `Promise.reject()` in my `validateInput()` function. As it currently stands when I click the `$continueButton` nothing happens. What should happen is that an input gets the error class added to it. – Carl Edwards Apr 08 '16 at 16:29
  • Now, when you've posted the function body I don't understand why do use promises. You haven't there any async operations, so you can just iterate by validations, and check each validator result, if it's false, do what you need and all. – alexmac Apr 08 '16 at 16:34
  • Let me make additional update to my code. I'll show you where the async operation takes place, which is in my `validateAddress()` function. – Carl Edwards Apr 08 '16 at 16:37
  • Updated the question. – Carl Edwards Apr 08 '16 at 16:39