d2-ui
Version:
124 lines (105 loc) • 5.57 kB
JavaScript
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
import { Observable, Subject } from 'rx';
/**
* Run `validatorFunctions` in parallel and returns a resolved `Promise` with the validation status.
* @param {function:Promise[]} validatorFunctions Array of validator functions that return a Promise.
* @param {*} value The value that should be checked by the given validators
* @returns {Promise.<Object>} Resolves promise with `{ isValid: true }` when validators passed
* or with `{ isValid: false, message: '<error_message>'`} when one of the validators failed. The `message` property
* contains the value that the failed validator function rejected with.
*/
function runValidatorFunctions(validatorFunctions, value) {
return Promise.all(validatorFunctions.map(function (validator) {
return validator.call(null, value);
}))
// All validators passed
.then(function () {
return { isValid: true };
})
// When one of the validators failed a failure status with error message are emitted
.catch(function (errorMessage) {
return { isValid: false, message: errorMessage };
});
}
/**
*
*/
var AsyncValidatorRunner = function () {
/**
*
* @param {Rx.Scheduler} [scheduler] Optional scheduler to be used for the Rx methods that can accept one.
*/
function AsyncValidatorRunner(scheduler) {
_classCallCheck(this, AsyncValidatorRunner);
// Rx.Scheduler to be used to run the operations on
this.scheduler = scheduler;
// Rx.Subject that will serve as the validator pipeline
// The Runner passes the fields and values and emits
// success
this.validatorPipeline = new Subject();
// The amount of time to be used for debouncing the field values
this.debounceTimeInMs = 400;
}
/**
* Run the `asyncValidators` passed for the field with `fieldName`. `fieldName` is only
* used to pass through to the result so `listenToValidatorsFor` can identify which field
* the result belong to.
*
* @param {string} fieldName The name of the field
* @param {Array<Function>} asyncValidators An array of functions that each return a Promise thar resolves on valid
* and rejects on failure.
* @param {*} value The value that should be checked for validity.
*
* @returns {AsyncValidatorObject} Returns itself for chaining purposes
*/
_createClass(AsyncValidatorRunner, [{
key: 'run',
value: function run(fieldName) {
var asyncValidators = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1];
var value = arguments[2];
this.validatorPipeline.onNext({ fieldName: fieldName, asyncValidators: asyncValidators, value: value });
return this;
}
/**
* Returns an Rx.Observable that can be subscribed to to be updated of validation results for the field
* with `fieldName`. This function when subscribing runs the validators that are passed for the given field when
* `run` was called. This allows for only running the validators that are at the time the validation request was
* issued were applicable to the field.
*
* @param {string} fieldName The name of the field to filter statuses for.
* @returns {Rx.Observable} Observable that represents validation results for the given `fieldName`.
*/
}, {
key: 'listenToValidatorsFor',
value: function listenToValidatorsFor(fieldName) {
return this.validatorPipeline
// Filter the values by fieldName to make sure we only deal with the values for the requested field
.filter(function (field) {
return field.fieldName === fieldName;
})
// Only process the latest value within the specified time window
.debounce(this.debounceTimeInMs, this.scheduler).map(function (field) {
return Observable.fromPromise(runValidatorFunctions(field.asyncValidators, field.value)).map(function (status) {
return Object.assign(status, { fieldName: field.fieldName, value: field.value });
});
})
// Flatten all observables in the correct order they should be processed
.concatAll();
}
/**
* Creates an instance of the AsyncValidatorRunner class
*
* @param {Rx.Scheduler} scheduler A scheduler to be used while running the pipeline operations
* @returns {AsyncValidatorRunner} The instantiated runner
* @static
*/
}], [{
key: 'create',
value: function create(scheduler) {
return new AsyncValidatorRunner(scheduler);
}
}]);
return AsyncValidatorRunner;
}();
export default AsyncValidatorRunner;