devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
176 lines (144 loc) • 4.99 kB
JavaScript
"use strict";
var typeUtils = require("../utils/type");
var isPromise = typeUtils.isPromise;
var isDeferred = typeUtils.isDeferred;
var extend = require("../utils/extend").extend;
var Callbacks = require("../utils/callbacks");
var deferredConfig = [{
method: "resolve",
handler: "done",
state: "resolved"
}, {
method: "reject",
handler: "fail",
state: "rejected"
}, {
method: "notify",
handler: "progress"
}];
var _Deferred = function Deferred() {
var that = this;
this._state = "pending";
this._promise = {};
deferredConfig.forEach(function (config) {
var methodName = config.method;
this[methodName + "Callbacks"] = new Callbacks();
this[methodName] = function () {
return this[methodName + "With"](this._promise, arguments);
}.bind(this);
this._promise[config.handler] = function (handler) {
if (!handler) return this;
var callbacks = that[methodName + "Callbacks"];
if (callbacks.fired()) {
handler.apply(that[methodName + "Context"], that[methodName + "Args"]);
} else {
callbacks.add(function (context, args) {
handler.apply(context, args);
}.bind(this));
}
return this;
};
}.bind(this));
this._promise.always = function (handler) {
return this.done(handler).fail(handler);
};
this._promise.catch = function (handler) {
return this.then(null, handler);
};
this._promise.then = function (resolve, reject) {
var result = new _Deferred();
["done", "fail"].forEach(function (method) {
var callback = method === "done" ? resolve : reject;
this[method](function () {
if (!callback) {
result[method === "done" ? "resolve" : "reject"].apply(this, arguments);
return;
}
var callbackResult = callback && callback.apply(this, arguments);
if (isDeferred(callbackResult)) {
callbackResult.done(result.resolve).fail(result.reject);
} else if (isPromise(callbackResult)) {
callbackResult.then(result.resolve, result.reject);
} else {
result.resolve.apply(this, callbackResult ? [callbackResult] : arguments);
}
});
}.bind(this));
return result.promise();
};
this._promise.state = function () {
return that._state;
};
this._promise.promise = function (args) {
return args ? extend(args, that._promise) : that._promise;
};
this._promise.promise(this);
};
deferredConfig.forEach(function (config) {
var methodName = config.method;
var state = config.state;
_Deferred.prototype[methodName + "With"] = function (context, args) {
var callbacks = this[methodName + "Callbacks"];
if (this.state() === "pending") {
this[methodName + "Args"] = args;
this[methodName + "Context"] = context;
if (state) this._state = state;
callbacks.fire(context, args);
}
return this;
};
});
exports.fromPromise = function (promise, context) {
if (isDeferred(promise)) {
return promise;
} else if (isPromise(promise)) {
var d = new _Deferred();
promise.then(function () {
d.resolveWith.apply(d, [context].concat([[].slice.call(arguments)]));
}, function () {
d.rejectWith.apply(d, [context].concat([[].slice.call(arguments)]));
});
return d;
}
return new _Deferred().resolveWith(context, [promise]);
};
var when = function when() {
if (arguments.length === 1) {
return exports.fromPromise(arguments[0]);
}
var values = [].slice.call(arguments),
contexts = [],
resolvedCount = 0,
deferred = new _Deferred();
var updateState = function updateState(i) {
return function (value) {
contexts[i] = this;
values[i] = arguments.length > 1 ? [].slice.call(arguments) : value;
resolvedCount++;
if (resolvedCount === values.length) {
deferred.resolveWith(contexts, values);
}
};
};
for (var i = 0; i < values.length; i++) {
if (isDeferred(values[i])) {
values[i].promise().done(updateState(i)).fail(deferred.reject);
} else {
resolvedCount++;
}
}
if (resolvedCount === values.length) {
deferred.resolveWith(contexts, values);
}
return deferred.promise();
};
exports.setStrategy = function (value) {
_Deferred = value.Deferred;
when = value.when;
};
exports.Deferred = function () {
return new _Deferred();
};
exports.when = function () {
return when.apply(this, arguments);
};