diff --git a/build/deft-debug.js b/build/deft-debug.js
index 0e8c875..10bd5e3 100644
--- a/build/deft-debug.js
+++ b/build/deft-debug.js
@@ -1599,7 +1599,7 @@ Ext.define('Deft.mixin.Controllable', {
Copyright (c) 2012 [DeftJS Framework Contributors](http://deftjs.org)
Open source under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
-Promise.when(), all(), any(), map() and reduce() methods adapted from:
+Promise.when(), all(), any(), some(), map() and reduce() methods adapted from:
[when.js](https://github.com/cujojs/when)
Copyright (c) B Cavalier & J Hann
Open source under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
@@ -1706,58 +1706,90 @@ Ext.define('Deft.promise.Promise', {
});
},
/**
- * Returns a new {@link Deft.promise.Promise} that will only resolve once any one of the the specified `promisesOrValues` has resolved.
- * The resolution value will be the resolution value of the triggering `promiseOrValue`.
+ * Initiates a competitive race, returning a new {@link Deft.promise.Promise} that will resolve when any one of the supplied `promisesOrValues`
+ * have resolved, or will reject when all `promisesOrValues` have rejected or cancelled.
+ * The resolution value will the first value of `promisesOrValues` to resolve.
*/
any: function(promisesOrValues) {
+ return this.some(promisesOrValues, 1).then({
+ success: function(values) {
+ return values[0];
+ }
+ });
+ },
+ /**
+ * Initiates a competitive race, returning a new {@link Deft.promise.Promise} that will resolve when `howMany` of the supplied `promisesOrValues`
+ * have resolved, or will reject when it becomes impossible for `howMany` to resolve.
+ * The resolution value will be an Array of the first `howMany` values of `promisesOrValues` to resolve.
+ */
+
+ some: function(promisesOrValues, howMany) {
return this.when(promisesOrValues).then({
success: function(promisesOrValues) {
- var cancelFunction, canceller, complete, deferred, failureFunction, index, progressFunction, promiseOrValue, rejecter, resolver, successFunction, updater, _i, _len;
+ var cancelFunction, canceller, complete, deferred, errorMessage, failureFunction, index, progressFunction, promiseOrValue, rejecter, remainingToReject, remainingToResolve, resolver, successFunction, updater, values, _i, _len;
+ values = [];
+ remainingToResolve = howMany;
+ remainingToReject = (promisesOrValues.length - remainingToResolve) + 1;
deferred = Ext.create('Deft.promise.Deferred');
- updater = function(progress) {
- deferred.update(progress);
- return progress;
- };
- resolver = function(value) {
- complete();
- deferred.resolve(value);
- return value;
- };
- rejecter = function(error) {
- complete();
- deferred.reject(error);
- return error;
- };
- canceller = function(reason) {
- complete();
- deferred.cancel(reason);
- return reason;
- };
- complete = function() {
- return updater = resolver = rejecter = canceller = Ext.emptyFn;
- };
- successFunction = function(value) {
- return resolver(value);
- };
- failureFunction = function(value) {
- return rejecter(value);
- };
- progressFunction = function(value) {
- return updater(value);
- };
- cancelFunction = function(value) {
- return canceller(value);
- };
- for (index = _i = 0, _len = promisesOrValues.length; _i < _len; index = ++_i) {
- promiseOrValue = promisesOrValues[index];
- if (index in promisesOrValues) {
- this.when(promiseOrValue).then({
- success: successFunction,
- failure: failureFunction,
- progress: progressFunction,
- cancel: cancelFunction
- });
+ if (promisesOrValues.length < howMany) {
+ deferred.reject(new Error('Too few Promises or values were supplied to obtain the requested number of resolved values.'));
+ } else {
+ errorMessage = howMany === 1 ? 'No Promises were resolved.' : 'Too few Promises were resolved.';
+ updater = function(progress) {
+ deferred.update(progress);
+ return progress;
+ };
+ resolver = function(value) {
+ values.push(value);
+ remainingToResolve--;
+ if (remainingToResolve === 0) {
+ complete();
+ deferred.resolve(values);
+ }
+ return value;
+ };
+ rejecter = function(error) {
+ remainingToReject--;
+ if (remainingToReject === 0) {
+ complete();
+ deferred.reject(new Error(errorMessage));
+ }
+ return error;
+ };
+ canceller = function(reason) {
+ remainingToReject--;
+ if (remainingToReject === 0) {
+ complete();
+ deferred.reject(new Error(errorMessage));
+ }
+ return reason;
+ };
+ complete = function() {
+ return updater = resolver = rejecter = canceller = Ext.emptyFn;
+ };
+ successFunction = function(value) {
+ return resolver(value);
+ };
+ failureFunction = function(value) {
+ return rejecter(value);
+ };
+ progressFunction = function(value) {
+ return updater(value);
+ };
+ cancelFunction = function(value) {
+ return canceller(value);
+ };
+ for (index = _i = 0, _len = promisesOrValues.length; _i < _len; index = ++_i) {
+ promiseOrValue = promisesOrValues[index];
+ if (index in promisesOrValues) {
+ this.when(promiseOrValue).then({
+ success: successFunction,
+ failure: failureFunction,
+ progress: progressFunction,
+ cancel: cancelFunction
+ });
+ }
}
}
return deferred.getPromise();
diff --git a/build/deft.js b/build/deft.js
index 59a6f72..17a8bb8 100644
--- a/build/deft.js
+++ b/build/deft.js
@@ -4,4 +4,4 @@ DeftJS 0.8.0pre
Copyright (c) 2012 [DeftJS Framework Contributors](http://deftjs.org)
Open source under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
*/
-Ext.define("Deft.core.Class",{alternateClassName:["Deft.Class"],statics:{registerPreprocessor:function(b,d,a,c){if(Ext.getVersion("extjs")&&Ext.getVersion("core").isLessThan("4.1.0")){Ext.Class.registerPreprocessor(b,function(e,f,g){return d.call(this,e,f,f,g)}).setDefaultPreprocessorPosition(b,a,c)}else{Ext.Class.registerPreprocessor(b,function(f,g,e,h){return d.call(this,f,g,e,h)},[b],a,c)}},hookOnClassCreated:function(a,b){if(Ext.getVersion("extjs")&&Ext.getVersion("core").isLessThan("4.1.0")){Ext.Function.interceptBefore(a,"onClassCreated",b)}else{Ext.Function.interceptBefore(a,"onCreated",b)}},hookOnClassExtended:function(c,b){var a;if(Ext.getVersion("extjs")&&Ext.getVersion("core").isLessThan("4.1.0")){a=function(d,e){return b.call(this,d,e,e)}}else{a=b}if(c.onClassExtended!=null){Ext.Function.interceptBefore(c,"onClassExtended",a)}else{c.onClassExtended=a}},extendsClass:function(c,b){try{if(Ext.getClassName(b)===c){return true}if(b!=null?b.superclass:void 0){if(Ext.getClassName(b.superclass)===c){return true}else{return Deft.Class.extendsClass(c,Ext.getClass(b.superclass))}}else{return false}}catch(a){return false}}}});Ext.define("Deft.log.Logger",{alternateClassName:["Deft.Logger"],singleton:true,log:function(b,a){if(a==null){a="info"}},error:function(a){this.log(a,"error")},info:function(a){this.log(a,"info")},verbose:function(a){this.log(a,"verbose")},warn:function(a){this.log(a,"warn")},deprecate:function(a){this.log(a,"deprecate")}},function(){var a;if(Ext.getVersion("extjs")!=null){this.log=function(c,b){if(b==null){b="info"}if(b==="verbose"){b==="info"}if(b==="deprecate"){b="warn"}Ext.log({msg:c,level:b})}}else{if(Ext.isFunction((a=Ext.Logger)!=null?a.log:void 0)){this.log=Ext.bind(Ext.Logger.log,Ext.Logger)}}});Ext.define("Deft.util.Function",{alternateClassName:["Deft.Function"],statics:{spread:function(b,a){return function(c){if(!Ext.isArray(c)){Ext.Error.raise({msg:"Error spreading passed Array over target function arguments: passed a non-Array."})}return b.apply(a,c)}},memoize:function(d,c,a){var b;b={};return function(f){var e;e=Ext.isFunction(a)?a.apply(c,arguments):f;if(!(e in b)){b[e]=d.apply(c,arguments)}return b[e]}}}});Ext.define("Deft.event.LiveEventListener",{alternateClassName:["Deft.LiveEventListener"],requires:["Ext.ComponentQuery"],constructor:function(c){var b,d,e,a;Ext.apply(this,c);this.components=[];d=Ext.ComponentQuery.query(this.selector,this.container);for(e=0,a=d.length;e-1},locateReferences:function(c,d,a){var b,e;b=c;if(this.isPropertyChain(d)){e=this.parsePropertyChain(c,d);if(!e){return null}c=e.host;d=e.target}if(Ext.isFunction(a)){return{target:this.locateTarget(c,d),handler:a}}else{if(Ext.isFunction(b[a])){return{target:this.locateTarget(c,d),handler:b[a]}}else{return null}}},parsePropertyChain:function(a,b){var c;if(Ext.isString(b)){c=b.split(".")}else{if(Ext.isArray(b)){c=b}else{return null}}if(c.length>1&&(this.locateTarget(a,c[0])!=null)){return this.parsePropertyChain(this.locateTarget(a,c[0]),c.slice(1))}else{if(this.isTargetObservable(a,c[0])){return{host:a,target:c[0]}}else{return null}}},destroy:function(){var d,c,a,b;b=this.listeners;for(c=0,a=b.length;c0){this.createObservers()}return this},controlView:function(a){if(a instanceof Ext.ClassManager.get("Ext.Container")){this.setView(a);this.registeredComponentReferences={};this.registeredComponentSelectors={};if(Ext.getVersion("extjs")!=null){if(this.getView().rendered){this.onViewInitialize()}else{this.getView().on("afterrender",this.onViewInitialize,this,{single:true})}}else{if(this.getView().initialized){this.onViewInitialize()}else{this.getView().on("initialize",this.onViewInitialize,this,{single:true})}}}else{Ext.Error.raise({msg:"Error constructing ViewController: the configured 'view' is not an Ext.Container."})}},init:function(){},destroy:function(){var b,a;for(b in this.registeredComponentReferences){this.removeComponentReference(b)}for(a in this.registeredComponentSelectors){this.removeComponentSelector(a)}this.removeObservers();return true},onViewInitialize:function(){var d,h,e,f,c,a,b,g;if(Ext.getVersion("extjs")!=null){this.getView().on("beforedestroy",this.onViewBeforeDestroy,this)}else{b=this;c=this.getView().destroy;this.getView().destroy=function(){if(b.destroy()){c.call(this)}}}g=this.control;for(h in g){d=g[h];a=null;if(h!=="view"){if(Ext.isString(d)){a=d}else{if(d.selector!=null){a=d.selector}else{a="#"+h}}}e=null;if(Ext.isObject(d.listeners)){e=d.listeners}else{if(!((d.selector!=null)||(d.live!=null))){e=d}}f=(d.live!=null)&&d.live;this.addComponentReference(h,a,f);this.addComponentSelector(a,e,f)}this.init()},onViewBeforeDestroy:function(){if(this.destroy()){this.getView().un("beforedestroy",this.onBeforeDestroy,this);return true}return false},addComponentReference:function(e,a,c){var b,d;if(c==null){c=false}Deft.Logger.log("Adding '"+e+"' component reference for selector: '"+a+"'.");if(this.registeredComponentReferences[e]!=null){Ext.Error.raise({msg:"Error adding component reference: an existing component reference was already registered as '"+e+"'."})}if(e!=="view"){b="get"+Ext.String.capitalize(e);if(this[b]==null){if(c){this[b]=Ext.Function.pass(this.getViewComponent,[a],this)}else{d=this.getViewComponent(a);if(d==null){Ext.Error.raise({msg:"Error locating component: no component(s) found matching '"+a+"'."})}this[b]=function(){return d}}this[b].generated=true}}this.registeredComponentReferences[e]=true},removeComponentReference:function(b){var a;Deft.Logger.log("Removing '"+b+"' component reference.");if(this.registeredComponentReferences[b]==null){Ext.Error.raise({msg:"Error removing component reference: no component reference is registered as '"+b+"'."})}if(b!=="view"){a="get"+Ext.String.capitalize(b);if(this[a].generated){this[a]=null}}delete this.registeredComponentReferences[b]},getViewComponent:function(a){var b;if(a!=null){b=Ext.ComponentQuery.query(a,this.getView());if(b.length===0){return null}else{if(b.length===1){return b[0]}else{return b}}}else{return this.getView()}},addComponentSelector:function(a,b,c){var d,e;if(c==null){c=false}Deft.Logger.log("Adding component selector for: '"+a+"'.");e=this.getComponentSelector(a);if(e!=null){Ext.Error.raise({msg:"Error adding component selector: an existing component selector was already registered for '"+a+"'."})}d=Ext.create("Deft.mvc.ComponentSelector",{view:this.getView(),selector:a,listeners:b,scope:this,live:c});this.registeredComponentSelectors[a]=d},removeComponentSelector:function(a){var b;Deft.Logger.log("Removing component selector for '"+a+"'.");b=this.getComponentSelector(a);if(b==null){Ext.Error.raise({msg:"Error removing component selector: no component selector registered for '"+a+"'."})}b.destroy();delete this.registeredComponentSelectors[a]},getComponentSelector:function(a){return this.registeredComponentSelectors[a]},createObservers:function(){var a,c,b;this.registeredObservers={};b=this.observe;for(c in b){a=b[c];this.addObserver(c,a)}},addObserver:function(c,b){var a;a=Ext.create("Deft.mvc.Observer",{host:this,target:c,events:b});return this.registeredObservers[c]=a},removeObservers:function(){var a,c,b;b=this.registeredObservers;for(c in b){a=b[c];a.destroy();delete this.registeredObservers[c]}}},function(){return Deft.Class.registerPreprocessor("observe",function(b,c,a,d){Deft.Class.hookOnClassExtended(c,function(f,h,e){var g;if(f.superclass&&((g=f.superclass)!=null?g.observe:void 0)&&Deft.Class.extendsClass("Deft.mvc.ViewController",f)){h.observe=Deft.mvc.Observer.mergeObserve(f.superclass.observe,h.observe)}})},"before","extend")});Ext.define("Deft.mvc.Application",{alternateClassName:["Deft.Application"],initialized:false,constructor:function(a){if(a==null){a={}}this.initConfig(a);Ext.onReady(function(){this.init();this.initialized=true},this);return this},init:function(){}});Ext.define("Deft.mixin.Controllable",{requires:["Ext.Container","Deft.core.Class","Deft.log.Logger"],onClassMixedIn:function(a){Deft.Logger.deprecate("Deft.mixin.Controllable has been deprecated and can now be omitted - simply use the 'controller' class annotation on its own.")}},function(){var a;if(Ext.getVersion("extjs")&&Ext.getVersion("core").isLessThan("4.1.0")){a=function(){return function(d){var b;if(d==null){d={}}if(this instanceof Ext.ClassManager.get("Ext.Container")&&!this.$controlled){try{b=Ext.create(this.controller,d.controllerConfig||this.controllerConfig||{})}catch(c){Deft.Logger.warn("Error initializing view controller: an error occurred while creating an instance of the specified controller: '"+this.controller+"'.");throw c}if(this.getController===void 0){this.getController=function(){return b}}this.$controlled=true;this.callOverridden(arguments);b.controlView(this);return this}return this.callOverridden(arguments)}}}else{a=function(){return function(d){var b;if(d==null){d={}}if(this instanceof Ext.ClassManager.get("Ext.Container")&&!this.$controlled){try{b=Ext.create(this.controller,d.controllerConfig||this.controllerConfig||{})}catch(c){Deft.Logger.warn("Error initializing view controller: an error occurred while creating an instance of the specified controller: '"+this.controller+"'.");throw c}if(this.getController===void 0){this.getController=function(){return b}}this.$controlled=true;this.callParent(arguments);b.controlView(this);return this}return this.callParent(arguments)}}}Deft.Class.registerPreprocessor("controller",function(d,e,b,f){var c;Deft.Class.hookOnClassCreated(b,function(g){g.override({constructor:a()})});Deft.Class.hookOnClassExtended(e,function(h,i,g){Deft.Class.hookOnClassCreated(g,function(j){j.override({constructor:a()})})});c=this;Ext.require([e.controller],function(){if(f!=null){f.call(c,d,e,b)}});return false},"before","extend")});Ext.define("Deft.promise.Promise",{alternateClassName:["Deft.Promise"],statics:{when:function(a){var b;if(a instanceof Ext.ClassManager.get("Deft.promise.Promise")||a instanceof Ext.ClassManager.get("Deft.promise.Deferred")){return a.then()}else{if(Ext.isObject(a)&&Ext.isFunction(a.then)){b=Ext.create("Deft.promise.Deferred");a.then(function(c){b.resolve(c)},function(c){b.reject(c)});return b.then()}else{b=Ext.create("Deft.promise.Deferred");b.resolve(a);return b.then()}}},all:function(a){return this.when(a).then({success:function(n){var q,l,i,h,r,d,e,j,p,k,m,c,f,s,g,b,o;r=Ext.create("Deft.promise.Deferred");s=n.length;c=new Array(n);m=0;g=function(t){r.update(t);return t};f=function(t,u){c[t]=u;m++;if(m===s){i();r.resolve(c)}return u};k=function(t){i();r.reject(t);return t};l=function(t){i();r.cancel(t);return t};i=function(){return g=f=k=l=Ext.emptyFn};h=function(t){return function(u){return f(t,u)}};d=function(t){return k(t)};j=function(t){return g(t)};q=function(t){return l(t)};for(e=b=0,o=n.length;b>>0;e=arguments;if(e.length<=1){while(true){if(d in g){c=g[d++];break}if(++d>=f){throw new TypeError()}}}else{c=e[1]}while(d-1},locateReferences:function(c,d,a){var b,e;b=c;if(this.isPropertyChain(d)){e=this.parsePropertyChain(c,d);if(!e){return null}c=e.host;d=e.target}if(Ext.isFunction(a)){return{target:this.locateTarget(c,d),handler:a}}else{if(Ext.isFunction(b[a])){return{target:this.locateTarget(c,d),handler:b[a]}}else{return null}}},parsePropertyChain:function(a,b){var c;if(Ext.isString(b)){c=b.split(".")}else{if(Ext.isArray(b)){c=b}else{return null}}if(c.length>1&&(this.locateTarget(a,c[0])!=null)){return this.parsePropertyChain(this.locateTarget(a,c[0]),c.slice(1))}else{if(this.isTargetObservable(a,c[0])){return{host:a,target:c[0]}}else{return null}}},destroy:function(){var d,c,a,b;b=this.listeners;for(c=0,a=b.length;c0){this.createObservers()}return this},controlView:function(a){if(a instanceof Ext.ClassManager.get("Ext.Container")){this.setView(a);this.registeredComponentReferences={};this.registeredComponentSelectors={};if(Ext.getVersion("extjs")!=null){if(this.getView().rendered){this.onViewInitialize()}else{this.getView().on("afterrender",this.onViewInitialize,this,{single:true})}}else{if(this.getView().initialized){this.onViewInitialize()}else{this.getView().on("initialize",this.onViewInitialize,this,{single:true})}}}else{Ext.Error.raise({msg:"Error constructing ViewController: the configured 'view' is not an Ext.Container."})}},init:function(){},destroy:function(){var b,a;for(b in this.registeredComponentReferences){this.removeComponentReference(b)}for(a in this.registeredComponentSelectors){this.removeComponentSelector(a)}this.removeObservers();return true},onViewInitialize:function(){var d,h,e,f,c,a,b,g;if(Ext.getVersion("extjs")!=null){this.getView().on("beforedestroy",this.onViewBeforeDestroy,this)}else{b=this;c=this.getView().destroy;this.getView().destroy=function(){if(b.destroy()){c.call(this)}}}g=this.control;for(h in g){d=g[h];a=null;if(h!=="view"){if(Ext.isString(d)){a=d}else{if(d.selector!=null){a=d.selector}else{a="#"+h}}}e=null;if(Ext.isObject(d.listeners)){e=d.listeners}else{if(!((d.selector!=null)||(d.live!=null))){e=d}}f=(d.live!=null)&&d.live;this.addComponentReference(h,a,f);this.addComponentSelector(a,e,f)}this.init()},onViewBeforeDestroy:function(){if(this.destroy()){this.getView().un("beforedestroy",this.onBeforeDestroy,this);return true}return false},addComponentReference:function(e,a,c){var b,d;if(c==null){c=false}Deft.Logger.log("Adding '"+e+"' component reference for selector: '"+a+"'.");if(this.registeredComponentReferences[e]!=null){Ext.Error.raise({msg:"Error adding component reference: an existing component reference was already registered as '"+e+"'."})}if(e!=="view"){b="get"+Ext.String.capitalize(e);if(this[b]==null){if(c){this[b]=Ext.Function.pass(this.getViewComponent,[a],this)}else{d=this.getViewComponent(a);if(d==null){Ext.Error.raise({msg:"Error locating component: no component(s) found matching '"+a+"'."})}this[b]=function(){return d}}this[b].generated=true}}this.registeredComponentReferences[e]=true},removeComponentReference:function(b){var a;Deft.Logger.log("Removing '"+b+"' component reference.");if(this.registeredComponentReferences[b]==null){Ext.Error.raise({msg:"Error removing component reference: no component reference is registered as '"+b+"'."})}if(b!=="view"){a="get"+Ext.String.capitalize(b);if(this[a].generated){this[a]=null}}delete this.registeredComponentReferences[b]},getViewComponent:function(a){var b;if(a!=null){b=Ext.ComponentQuery.query(a,this.getView());if(b.length===0){return null}else{if(b.length===1){return b[0]}else{return b}}}else{return this.getView()}},addComponentSelector:function(a,b,c){var d,e;if(c==null){c=false}Deft.Logger.log("Adding component selector for: '"+a+"'.");e=this.getComponentSelector(a);if(e!=null){Ext.Error.raise({msg:"Error adding component selector: an existing component selector was already registered for '"+a+"'."})}d=Ext.create("Deft.mvc.ComponentSelector",{view:this.getView(),selector:a,listeners:b,scope:this,live:c});this.registeredComponentSelectors[a]=d},removeComponentSelector:function(a){var b;Deft.Logger.log("Removing component selector for '"+a+"'.");b=this.getComponentSelector(a);if(b==null){Ext.Error.raise({msg:"Error removing component selector: no component selector registered for '"+a+"'."})}b.destroy();delete this.registeredComponentSelectors[a]},getComponentSelector:function(a){return this.registeredComponentSelectors[a]},createObservers:function(){var a,c,b;this.registeredObservers={};b=this.observe;for(c in b){a=b[c];this.addObserver(c,a)}},addObserver:function(c,b){var a;a=Ext.create("Deft.mvc.Observer",{host:this,target:c,events:b});return this.registeredObservers[c]=a},removeObservers:function(){var a,c,b;b=this.registeredObservers;for(c in b){a=b[c];a.destroy();delete this.registeredObservers[c]}}},function(){return Deft.Class.registerPreprocessor("observe",function(b,c,a,d){Deft.Class.hookOnClassExtended(c,function(f,h,e){var g;if(f.superclass&&((g=f.superclass)!=null?g.observe:void 0)&&Deft.Class.extendsClass("Deft.mvc.ViewController",f)){h.observe=Deft.mvc.Observer.mergeObserve(f.superclass.observe,h.observe)}})},"before","extend")});Ext.define("Deft.mvc.Application",{alternateClassName:["Deft.Application"],initialized:false,constructor:function(a){if(a==null){a={}}this.initConfig(a);Ext.onReady(function(){this.init();this.initialized=true},this);return this},init:function(){}});Ext.define("Deft.mixin.Controllable",{requires:["Ext.Container","Deft.core.Class","Deft.log.Logger"],onClassMixedIn:function(a){Deft.Logger.deprecate("Deft.mixin.Controllable has been deprecated and can now be omitted - simply use the 'controller' class annotation on its own.")}},function(){var a;if(Ext.getVersion("extjs")&&Ext.getVersion("core").isLessThan("4.1.0")){a=function(){return function(d){var b;if(d==null){d={}}if(this instanceof Ext.ClassManager.get("Ext.Container")&&!this.$controlled){try{b=Ext.create(this.controller,d.controllerConfig||this.controllerConfig||{})}catch(c){Deft.Logger.warn("Error initializing view controller: an error occurred while creating an instance of the specified controller: '"+this.controller+"'.");throw c}if(this.getController===void 0){this.getController=function(){return b}}this.$controlled=true;this.callOverridden(arguments);b.controlView(this);return this}return this.callOverridden(arguments)}}}else{a=function(){return function(d){var b;if(d==null){d={}}if(this instanceof Ext.ClassManager.get("Ext.Container")&&!this.$controlled){try{b=Ext.create(this.controller,d.controllerConfig||this.controllerConfig||{})}catch(c){Deft.Logger.warn("Error initializing view controller: an error occurred while creating an instance of the specified controller: '"+this.controller+"'.");throw c}if(this.getController===void 0){this.getController=function(){return b}}this.$controlled=true;this.callParent(arguments);b.controlView(this);return this}return this.callParent(arguments)}}}Deft.Class.registerPreprocessor("controller",function(d,e,b,f){var c;Deft.Class.hookOnClassCreated(b,function(g){g.override({constructor:a()})});Deft.Class.hookOnClassExtended(e,function(h,i,g){Deft.Class.hookOnClassCreated(g,function(j){j.override({constructor:a()})})});c=this;Ext.require([e.controller],function(){if(f!=null){f.call(c,d,e,b)}});return false},"before","extend")});Ext.define("Deft.promise.Promise",{alternateClassName:["Deft.Promise"],statics:{when:function(a){var b;if(a instanceof Ext.ClassManager.get("Deft.promise.Promise")||a instanceof Ext.ClassManager.get("Deft.promise.Deferred")){return a.then()}else{if(Ext.isObject(a)&&Ext.isFunction(a.then)){b=Ext.create("Deft.promise.Deferred");a.then(function(c){b.resolve(c)},function(c){b.reject(c)});return b.then()}else{b=Ext.create("Deft.promise.Deferred");b.resolve(a);return b.then()}}},all:function(a){return this.when(a).then({success:function(n){var q,l,i,h,r,d,e,j,p,k,m,c,f,s,g,b,o;r=Ext.create("Deft.promise.Deferred");s=n.length;c=new Array(n);m=0;g=function(t){r.update(t);return t};f=function(t,u){c[t]=u;m++;if(m===s){i();r.resolve(c)}return u};k=function(t){i();r.reject(t);return t};l=function(t){i();r.cancel(t);return t};i=function(){return g=f=k=l=Ext.emptyFn};h=function(t){return function(u){return f(t,u)}};d=function(t){return k(t)};j=function(t){return g(t)};q=function(t){return l(t)};for(e=b=0,o=n.length;b>>0;e=arguments;if(e.length<=1){while(true){if(d in g){c=g[d++];break}if(++d>=f){throw new TypeError()}}}else{c=e[1]}while(d
return @actual.getState() is 'resolved' and wasSpyCalledWith( successCallback, value ) and not wasSpyCalled( failureCallback ) and not wasSpyCalled( progressCallback ) and not wasSpyCalled( cancelCallback )
- toRejectWith: ( message ) ->
+ toRejectWith: ( error ) ->
successCallback = jasmine.createSpy( 'success callback' )
failureCallback = jasmine.createSpy( 'failure callback' )
progressCallback = jasmine.createSpy( 'progress callback' )
@@ -93,7 +93,7 @@ describe( 'Deft.promise.Promise', ->
cancel: cancelCallback
)
- return @actual.getState() is 'rejected' and not wasSpyCalled( successCallback ) and wasSpyCalledWith( failureCallback, message ) and not wasSpyCalled( progressCallback ) and not wasSpyCalled( cancelCallback )
+ return @actual.getState() is 'rejected' and not wasSpyCalled( successCallback ) and wasSpyCalledWith( failureCallback, error ) and not wasSpyCalled( progressCallback ) and not wasSpyCalled( cancelCallback )
toUpdateWith: ( progress ) ->
successCallback = jasmine.createSpy( 'success callback' )
@@ -1070,8 +1070,13 @@ describe( 'Deft.promise.Promise', ->
describe( 'with a variety of combinations of values, Deferreds and Promises specified', ->
- it( 'should return a resolved Promise when an Array containing any combination of pending Deferreds and/or pending Promises and a value is specified', ->
- parameters = [ Ext.create( 'Deft.promise.Deferred' ), Ext.create( 'Deft.promise.Deferred' ).getPromise() ]
+ it( 'should return a resolved Promise when an Array containing any combination of pending, rejected and/or cancelled Deferreds and/or Promises, and a value is specified', ->
+ pendingDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred.reject( 'error message' )
+ cancelledDeferred = Ext.create( 'Deft.promise.Deferred' )
+ cancelledDeferred.cancel( 'reason' )
+ parameters = [ pendingDeferred, pendingDeferred.getPromise(), rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise() ]
for combination in generateCombinations( parameters ).concat( [] )
for permutation in generatePermutations( combination.concat( 'expected result' ) )
@@ -1090,8 +1095,13 @@ describe( 'Deft.promise.Promise', ->
return
)
- it( 'should return a resolved Promise when an Array containing any combination of pending Deferreds and/or pending Promises and a resolved Deferred or Promise is specified', ->
- parameters = [ Ext.create( 'Deft.promise.Deferred' ), Ext.create( 'Deft.promise.Deferred' ).getPromise() ]
+ it( 'should return a resolved Promise when an Array containing any combination of pending, rejected and/or cancelled Deferreds and/or Promises, and a resolved Deferred or Promise is specified', ->
+ pendingDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred.reject( 'error message' )
+ cancelledDeferred = Ext.create( 'Deft.promise.Deferred' )
+ cancelledDeferred.cancel( 'reason' )
+ parameters = [ pendingDeferred, pendingDeferred.getPromise(), rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise() ]
resolvedDeferred = Ext.create( 'Deft.promise.Deferred' )
resolvedDeferred.resolve( 'expected result' )
@@ -1112,28 +1122,35 @@ describe( 'Deft.promise.Promise', ->
return
)
- it( 'should return a rejected Promise when an Array containing any combination of pending Deferreds, and/or pending Promises, and a rejected Deferred or Promise is specified', ->
- parameters = [ Ext.create( 'Deft.promise.Deferred' ), Ext.create( 'Deft.promise.Deferred' ).getPromise() ]
+ it( 'should return a rejected Promise when an Array containing any combination of rejected and/or cancelled Deferreds and/or Promises is specified', ->
rejectedDeferred = Ext.create( 'Deft.promise.Deferred' )
rejectedDeferred.reject( 'error message' )
+ cancelledDeferred = Ext.create( 'Deft.promise.Deferred' )
+ cancelledDeferred.cancel( 'reason' )
+ parameters = [ rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise() ]
- for combination in generateCombinations( parameters ).concat( [] )
- for permutation in generatePermutations( combination.concat( rejectedDeferred ) )
+ for combination in generateCombinations( parameters )
+ for permutation in generatePermutations( combination )
promise = Deft.promise.Promise.any( permutation )
expect( promise ).toBeInstanceOf( 'Deft.promise.Promise' )
- expect( promise ).toRejectWith( 'error message' )
+ expect( promise ).toRejectWith( new Error( 'No Promises were resolved.' ) )
- for combination in generateCombinations( parameters ).concat( [] )
- for permutation in generatePermutations( combination.concat( rejectedDeferred.getPromise() ) )
+ for combination in generateCombinations( parameters )
+ for permutation in generatePermutations( combination )
promise = Deft.promise.Promise.any( permutation )
expect( promise ).toBeInstanceOf( 'Deft.promise.Promise' )
- expect( promise ).toRejectWith( 'error message' )
+ expect( promise ).toRejectWith( new Error( 'No Promises were resolved.' ) )
)
- it( 'should return a pending (and immediately updated) Promise when an Array containing any combination of pending Deferreds, and/or pending Promises, and pending (and updated) Deferred or Promise is specified', ->
- parameters = [ Ext.create( 'Deft.promise.Deferred' ), Ext.create( 'Deft.promise.Deferred' ).getPromise() ]
+ it( 'should return a pending (and immediately updated) Promise when an Array containing any combination of pending, rejected and/or cancelled Deferreds and/or Promises, and a pending (and updated) Deferred or Promise is specified', ->
+ pendingDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred.reject( 'error message' )
+ cancelledDeferred = Ext.create( 'Deft.promise.Deferred' )
+ cancelledDeferred.cancel( 'reason' )
+ parameters = [ pendingDeferred, pendingDeferred.getPromise(), rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise() ]
updatedDeferred = Ext.create( 'Deft.promise.Deferred' )
updatedDeferred.update( 'progress' )
@@ -1152,28 +1169,13 @@ describe( 'Deft.promise.Promise', ->
expect( promise ).toUpdateWith( 'progress' )
)
- it( 'should return a cancelled Promise when an Array containing any combination of pending Deferreds, and/or pending Promises, and a cancelled Deferred or Promise is specified', ->
- parameters = [ Ext.create( 'Deft.promise.Deferred' ), Ext.create( 'Deft.promise.Deferred' ).getPromise() ]
+ it( 'should return a resolved Promise when an Array containing any combination of pending, rejected and/or cancelled Deferreds and/or Promises, and a pending Deferred or Promise is specified that is later resolved', ->
+ pendingDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred.reject( 'error message' )
cancelledDeferred = Ext.create( 'Deft.promise.Deferred' )
cancelledDeferred.cancel( 'reason' )
-
- for combination in generateCombinations( parameters ).concat( [] )
- for permutation in generatePermutations( combination.concat( cancelledDeferred ) )
- promise = Deft.promise.Promise.any( permutation )
-
- expect( promise ).toBeInstanceOf( 'Deft.promise.Promise' )
- expect( promise ).toCancelWith( 'reason' )
-
- for combination in generateCombinations( parameters ).concat( [] )
- for permutation in generatePermutations( combination.concat( cancelledDeferred.getPromise() ) )
- promise = Deft.promise.Promise.any( permutation )
-
- expect( promise ).toBeInstanceOf( 'Deft.promise.Promise' )
- expect( promise ).toCancelWith( 'reason' )
- )
-
- it( 'should return a resolved Promise when an Array containing any combination of pending Deferreds and/or pending Promises, and a pending Deferred or Promise is specified that is later resolved', ->
- parameters = [ Ext.create( 'Deft.promise.Deferred' ), Ext.create( 'Deft.promise.Deferred' ).getPromise() ]
+ parameters = [ pendingDeferred, pendingDeferred.getPromise(), rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise() ]
placeholder = {}
for combination in generateCombinations( parameters ).concat( [] )
@@ -1209,8 +1211,12 @@ describe( 'Deft.promise.Promise', ->
return
)
- it( 'should return a rejected Promise when an Array containing any combination of pending Deferreds and/or pending Promises, and a pending Deferred or Promise is specified that is later rejected', ->
- parameters = [ Ext.create( 'Deft.promise.Deferred' ), Ext.create( 'Deft.promise.Deferred' ).getPromise() ]
+ it( 'should return a rejected Promise when an Array containing any combination of rejected and/or cancelled Deferreds and/or Promises, and a pending Deferred or Promise is specified that is later rejected', ->
+ rejectedDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred.reject( 'error message' )
+ cancelledDeferred = Ext.create( 'Deft.promise.Deferred' )
+ cancelledDeferred.cancel( 'reason' )
+ parameters = [ rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise() ]
placeholder = {}
for combination in generateCombinations( parameters ).concat( [] )
@@ -1226,7 +1232,7 @@ describe( 'Deft.promise.Promise', ->
pendingDeferred.reject( 'error message' )
- expect( promise ).toRejectWith( 'error message' )
+ expect( promise ).toRejectWith( new Error( 'No Promises were resolved.' ) )
for combination in generateCombinations( parameters ).concat( [] )
for permutation in generatePermutations( combination.concat( placeholder ) )
@@ -1241,13 +1247,18 @@ describe( 'Deft.promise.Promise', ->
pendingDeferred.reject( 'error message' )
- expect( promise ).toRejectWith( 'error message' )
+ expect( promise ).toRejectWith( new Error( 'No Promises were resolved.' ) )
return
)
- it( 'should return a pending (and later updated) when an Array containing any combination of pending Deferreds and/or pending Promises, and a pending Deferred or Promise is specified that is later updated', ->
- parameters = [ Ext.create( 'Deft.promise.Deferred' ), Ext.create( 'Deft.promise.Deferred' ).getPromise() ]
+ it( 'should return a pending (and later updated) when an Array containing any combination of pending, rejected and/or Deferreds and/or Promises, and a pending Deferred or Promise is specified that is later updated', ->
+ pendingDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred.reject( 'error message' )
+ cancelledDeferred = Ext.create( 'Deft.promise.Deferred' )
+ cancelledDeferred.cancel( 'reason' )
+ parameters = [ pendingDeferred, pendingDeferred.getPromise(), rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise() ]
placeholder = {}
for combination in generateCombinations( parameters ).concat( [] )
@@ -1283,8 +1294,12 @@ describe( 'Deft.promise.Promise', ->
return
)
- it( 'should return a cancelled Promise when an Array containing any combination of pending Deferreds and/or pending Promises, and a pending Deferred or Promise is specified that is later cancelled', ->
- parameters = [ Ext.create( 'Deft.promise.Deferred' ), Ext.create( 'Deft.promise.Deferred' ).getPromise() ]
+ it( 'should return a rejected Promise when an Array containing any combination of rejected and/or cancelled Deferreds and/or Promises, and a pending Deferred or Promise is specified that is later cancelled', ->
+ rejectedDeferred = Ext.create( 'Deft.promise.Deferred' )
+ rejectedDeferred.reject( 'error message' )
+ cancelledDeferred = Ext.create( 'Deft.promise.Deferred' )
+ cancelledDeferred.cancel( 'reason' )
+ parameters = [ rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise() ]
placeholder = {}
for combination in generateCombinations( parameters ).concat( [] )
@@ -1300,7 +1315,7 @@ describe( 'Deft.promise.Promise', ->
pendingDeferred.cancel( 'reason' )
- expect( promise ).toCancelWith( 'reason' )
+ expect( promise ).toRejectWith( new Error( 'No Promises were resolved.' ) )
for combination in generateCombinations( parameters ).concat( [] )
for permutation in generatePermutations( combination.concat( placeholder ) )
@@ -1315,7 +1330,7 @@ describe( 'Deft.promise.Promise', ->
pendingDeferred.cancel( 'reason' )
- expect( promise ).toCancelWith( 'reason' )
+ expect( promise ).toRejectWith( new Error( 'No Promises were resolved.' ) )
return
)
diff --git a/spec/js/Deft/promise/Promise.js b/spec/js/Deft/promise/Promise.js
index f51ee5d..80da334 100644
--- a/spec/js/Deft/promise/Promise.js
+++ b/spec/js/Deft/promise/Promise.js
@@ -86,7 +86,7 @@ describe('Deft.promise.Promise', function() {
});
return this.actual.getState() === 'resolved' && wasSpyCalledWith(successCallback, value) && !wasSpyCalled(failureCallback) && !wasSpyCalled(progressCallback) && !wasSpyCalled(cancelCallback);
},
- toRejectWith: function(message) {
+ toRejectWith: function(error) {
var cancelCallback, failureCallback, progressCallback, successCallback;
successCallback = jasmine.createSpy('success callback');
failureCallback = jasmine.createSpy('failure callback');
@@ -98,7 +98,7 @@ describe('Deft.promise.Promise', function() {
progress: progressCallback,
cancel: cancelCallback
});
- return this.actual.getState() === 'rejected' && !wasSpyCalled(successCallback) && wasSpyCalledWith(failureCallback, message) && !wasSpyCalled(progressCallback) && !wasSpyCalled(cancelCallback);
+ return this.actual.getState() === 'rejected' && !wasSpyCalled(successCallback) && wasSpyCalledWith(failureCallback, error) && !wasSpyCalled(progressCallback) && !wasSpyCalled(cancelCallback);
},
toUpdateWith: function(progress) {
var cancelCallback, failureCallback, progressCallback, successCallback;
@@ -936,9 +936,14 @@ describe('Deft.promise.Promise', function() {
}
});
describe('with a variety of combinations of values, Deferreds and Promises specified', function() {
- it('should return a resolved Promise when an Array containing any combination of pending Deferreds and/or pending Promises and a value is specified', function() {
- var combination, parameters, permutation, promise, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
- parameters = [Ext.create('Deft.promise.Deferred'), Ext.create('Deft.promise.Deferred').getPromise()];
+ it('should return a resolved Promise when an Array containing any combination of pending, rejected and/or cancelled Deferreds and/or Promises, and a value is specified', function() {
+ var cancelledDeferred, combination, parameters, pendingDeferred, permutation, promise, rejectedDeferred, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
+ pendingDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred.reject('error message');
+ cancelledDeferred = Ext.create('Deft.promise.Deferred');
+ cancelledDeferred.cancel('reason');
+ parameters = [pendingDeferred, pendingDeferred.getPromise(), rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise()];
_ref = generateCombinations(parameters).concat([]);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
combination = _ref[_i];
@@ -962,9 +967,14 @@ describe('Deft.promise.Promise', function() {
}
}
});
- it('should return a resolved Promise when an Array containing any combination of pending Deferreds and/or pending Promises and a resolved Deferred or Promise is specified', function() {
- var combination, parameters, permutation, promise, resolvedDeferred, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
- parameters = [Ext.create('Deft.promise.Deferred'), Ext.create('Deft.promise.Deferred').getPromise()];
+ it('should return a resolved Promise when an Array containing any combination of pending, rejected and/or cancelled Deferreds and/or Promises, and a resolved Deferred or Promise is specified', function() {
+ var cancelledDeferred, combination, parameters, pendingDeferred, permutation, promise, rejectedDeferred, resolvedDeferred, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
+ pendingDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred.reject('error message');
+ cancelledDeferred = Ext.create('Deft.promise.Deferred');
+ cancelledDeferred.cancel('reason');
+ parameters = [pendingDeferred, pendingDeferred.getPromise(), rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise()];
resolvedDeferred = Ext.create('Deft.promise.Deferred');
resolvedDeferred.resolve('expected result');
_ref = generateCombinations(parameters).concat([]);
@@ -990,44 +1000,51 @@ describe('Deft.promise.Promise', function() {
}
}
});
- it('should return a rejected Promise when an Array containing any combination of pending Deferreds, and/or pending Promises, and a rejected Deferred or Promise is specified', function() {
- var combination, parameters, permutation, promise, rejectedDeferred, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
- parameters = [Ext.create('Deft.promise.Deferred'), Ext.create('Deft.promise.Deferred').getPromise()];
+ it('should return a rejected Promise when an Array containing any combination of rejected and/or cancelled Deferreds and/or Promises is specified', function() {
+ var cancelledDeferred, combination, parameters, permutation, promise, rejectedDeferred, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
rejectedDeferred = Ext.create('Deft.promise.Deferred');
rejectedDeferred.reject('error message');
- _ref = generateCombinations(parameters).concat([]);
+ cancelledDeferred = Ext.create('Deft.promise.Deferred');
+ cancelledDeferred.cancel('reason');
+ parameters = [rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise()];
+ _ref = generateCombinations(parameters);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
combination = _ref[_i];
- _ref1 = generatePermutations(combination.concat(rejectedDeferred));
+ _ref1 = generatePermutations(combination);
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
permutation = _ref1[_j];
promise = Deft.promise.Promise.any(permutation);
expect(promise).toBeInstanceOf('Deft.promise.Promise');
- expect(promise).toRejectWith('error message');
+ expect(promise).toRejectWith(new Error('No Promises were resolved.'));
}
}
- _ref2 = generateCombinations(parameters).concat([]);
+ _ref2 = generateCombinations(parameters);
_results = [];
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
combination = _ref2[_k];
_results.push((function() {
var _l, _len3, _ref3, _results1;
- _ref3 = generatePermutations(combination.concat(rejectedDeferred.getPromise()));
+ _ref3 = generatePermutations(combination);
_results1 = [];
for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
permutation = _ref3[_l];
promise = Deft.promise.Promise.any(permutation);
expect(promise).toBeInstanceOf('Deft.promise.Promise');
- _results1.push(expect(promise).toRejectWith('error message'));
+ _results1.push(expect(promise).toRejectWith(new Error('No Promises were resolved.')));
}
return _results1;
})());
}
return _results;
});
- it('should return a pending (and immediately updated) Promise when an Array containing any combination of pending Deferreds, and/or pending Promises, and pending (and updated) Deferred or Promise is specified', function() {
- var combination, parameters, permutation, promise, updatedDeferred, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
- parameters = [Ext.create('Deft.promise.Deferred'), Ext.create('Deft.promise.Deferred').getPromise()];
+ it('should return a pending (and immediately updated) Promise when an Array containing any combination of pending, rejected and/or cancelled Deferreds and/or Promises, and a pending (and updated) Deferred or Promise is specified', function() {
+ var cancelledDeferred, combination, parameters, pendingDeferred, permutation, promise, rejectedDeferred, updatedDeferred, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
+ pendingDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred.reject('error message');
+ cancelledDeferred = Ext.create('Deft.promise.Deferred');
+ cancelledDeferred.cancel('reason');
+ parameters = [pendingDeferred, pendingDeferred.getPromise(), rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise()];
updatedDeferred = Ext.create('Deft.promise.Deferred');
updatedDeferred.update('progress');
_ref = generateCombinations(parameters).concat([]);
@@ -1060,44 +1077,14 @@ describe('Deft.promise.Promise', function() {
}
return _results;
});
- it('should return a cancelled Promise when an Array containing any combination of pending Deferreds, and/or pending Promises, and a cancelled Deferred or Promise is specified', function() {
- var cancelledDeferred, combination, parameters, permutation, promise, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
- parameters = [Ext.create('Deft.promise.Deferred'), Ext.create('Deft.promise.Deferred').getPromise()];
+ it('should return a resolved Promise when an Array containing any combination of pending, rejected and/or cancelled Deferreds and/or Promises, and a pending Deferred or Promise is specified that is later resolved', function() {
+ var cancelledDeferred, combination, parameters, pendingDeferred, permutation, placeholder, promise, rejectedDeferred, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
+ pendingDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred.reject('error message');
cancelledDeferred = Ext.create('Deft.promise.Deferred');
cancelledDeferred.cancel('reason');
- _ref = generateCombinations(parameters).concat([]);
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
- combination = _ref[_i];
- _ref1 = generatePermutations(combination.concat(cancelledDeferred));
- for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
- permutation = _ref1[_j];
- promise = Deft.promise.Promise.any(permutation);
- expect(promise).toBeInstanceOf('Deft.promise.Promise');
- expect(promise).toCancelWith('reason');
- }
- }
- _ref2 = generateCombinations(parameters).concat([]);
- _results = [];
- for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
- combination = _ref2[_k];
- _results.push((function() {
- var _l, _len3, _ref3, _results1;
- _ref3 = generatePermutations(combination.concat(cancelledDeferred.getPromise()));
- _results1 = [];
- for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
- permutation = _ref3[_l];
- promise = Deft.promise.Promise.any(permutation);
- expect(promise).toBeInstanceOf('Deft.promise.Promise');
- _results1.push(expect(promise).toCancelWith('reason'));
- }
- return _results1;
- })());
- }
- return _results;
- });
- it('should return a resolved Promise when an Array containing any combination of pending Deferreds and/or pending Promises, and a pending Deferred or Promise is specified that is later resolved', function() {
- var combination, parameters, pendingDeferred, permutation, placeholder, promise, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
- parameters = [Ext.create('Deft.promise.Deferred'), Ext.create('Deft.promise.Deferred').getPromise()];
+ parameters = [pendingDeferred, pendingDeferred.getPromise(), rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise()];
placeholder = {};
_ref = generateCombinations(parameters).concat([]);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@@ -1130,9 +1117,13 @@ describe('Deft.promise.Promise', function() {
}
}
});
- it('should return a rejected Promise when an Array containing any combination of pending Deferreds and/or pending Promises, and a pending Deferred or Promise is specified that is later rejected', function() {
- var combination, parameters, pendingDeferred, permutation, placeholder, promise, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
- parameters = [Ext.create('Deft.promise.Deferred'), Ext.create('Deft.promise.Deferred').getPromise()];
+ it('should return a rejected Promise when an Array containing any combination of rejected and/or cancelled Deferreds and/or Promises, and a pending Deferred or Promise is specified that is later rejected', function() {
+ var cancelledDeferred, combination, parameters, pendingDeferred, permutation, placeholder, promise, rejectedDeferred, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
+ rejectedDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred.reject('error message');
+ cancelledDeferred = Ext.create('Deft.promise.Deferred');
+ cancelledDeferred.cancel('reason');
+ parameters = [rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise()];
placeholder = {};
_ref = generateCombinations(parameters).concat([]);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@@ -1146,7 +1137,7 @@ describe('Deft.promise.Promise', function() {
expect(promise).toBeInstanceOf('Deft.promise.Promise');
expect(promise.getState()).toBe('pending');
pendingDeferred.reject('error message');
- expect(promise).toRejectWith('error message');
+ expect(promise).toRejectWith(new Error('No Promises were resolved.'));
}
}
_ref2 = generateCombinations(parameters).concat([]);
@@ -1161,13 +1152,18 @@ describe('Deft.promise.Promise', function() {
expect(promise).toBeInstanceOf('Deft.promise.Promise');
expect(promise.getState()).toBe('pending');
pendingDeferred.reject('error message');
- expect(promise).toRejectWith('error message');
+ expect(promise).toRejectWith(new Error('No Promises were resolved.'));
}
}
});
- it('should return a pending (and later updated) when an Array containing any combination of pending Deferreds and/or pending Promises, and a pending Deferred or Promise is specified that is later updated', function() {
- var combination, parameters, pendingDeferred, permutation, placeholder, promise, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
- parameters = [Ext.create('Deft.promise.Deferred'), Ext.create('Deft.promise.Deferred').getPromise()];
+ it('should return a pending (and later updated) when an Array containing any combination of pending, rejected and/or Deferreds and/or Promises, and a pending Deferred or Promise is specified that is later updated', function() {
+ var cancelledDeferred, combination, parameters, pendingDeferred, permutation, placeholder, promise, rejectedDeferred, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
+ pendingDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred.reject('error message');
+ cancelledDeferred = Ext.create('Deft.promise.Deferred');
+ cancelledDeferred.cancel('reason');
+ parameters = [pendingDeferred, pendingDeferred.getPromise(), rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise()];
placeholder = {};
_ref = generateCombinations(parameters).concat([]);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@@ -1200,9 +1196,13 @@ describe('Deft.promise.Promise', function() {
}
}
});
- it('should return a cancelled Promise when an Array containing any combination of pending Deferreds and/or pending Promises, and a pending Deferred or Promise is specified that is later cancelled', function() {
- var combination, parameters, pendingDeferred, permutation, placeholder, promise, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
- parameters = [Ext.create('Deft.promise.Deferred'), Ext.create('Deft.promise.Deferred').getPromise()];
+ it('should return a rejected Promise when an Array containing any combination of rejected and/or cancelled Deferreds and/or Promises, and a pending Deferred or Promise is specified that is later cancelled', function() {
+ var cancelledDeferred, combination, parameters, pendingDeferred, permutation, placeholder, promise, rejectedDeferred, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3;
+ rejectedDeferred = Ext.create('Deft.promise.Deferred');
+ rejectedDeferred.reject('error message');
+ cancelledDeferred = Ext.create('Deft.promise.Deferred');
+ cancelledDeferred.cancel('reason');
+ parameters = [rejectedDeferred, rejectedDeferred.getPromise(), cancelledDeferred, cancelledDeferred.getPromise()];
placeholder = {};
_ref = generateCombinations(parameters).concat([]);
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
@@ -1216,7 +1216,7 @@ describe('Deft.promise.Promise', function() {
expect(promise).toBeInstanceOf('Deft.promise.Promise');
expect(promise.getState()).toBe('pending');
pendingDeferred.cancel('reason');
- expect(promise).toCancelWith('reason');
+ expect(promise).toRejectWith(new Error('No Promises were resolved.'));
}
}
_ref2 = generateCombinations(parameters).concat([]);
@@ -1231,7 +1231,7 @@ describe('Deft.promise.Promise', function() {
expect(promise).toBeInstanceOf('Deft.promise.Promise');
expect(promise.getState()).toBe('pending');
pendingDeferred.cancel('reason');
- expect(promise).toCancelWith('reason');
+ expect(promise).toRejectWith(new Error('No Promises were resolved.'));
}
}
});
diff --git a/src/coffee/Deft/promise/Promise.coffee b/src/coffee/Deft/promise/Promise.coffee
index a53d2e0..4dfe1f9 100644
--- a/src/coffee/Deft/promise/Promise.coffee
+++ b/src/coffee/Deft/promise/Promise.coffee
@@ -2,7 +2,7 @@
Copyright (c) 2012 [DeftJS Framework Contributors](http://deftjs.org)
Open source under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
-Promise.when(), all(), any(), map() and reduce() methods adapted from:
+Promise.when(), all(), any(), some(), map() and reduce() methods adapted from:
[when.js](https://github.com/cujojs/when)
Copyright (c) B Cavalier & J Hann
Open source under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
@@ -97,47 +97,72 @@ Ext.define( 'Deft.promise.Promise',
###*
- * Returns a new {@link Deft.promise.Promise} that will only resolve once any one of the the specified `promisesOrValues` has resolved.
- * The resolution value will be the resolution value of the triggering `promiseOrValue`.
+ * Initiates a competitive race, returning a new {@link Deft.promise.Promise} that will resolve when any one of the supplied `promisesOrValues`
+ * have resolved, or will reject when all `promisesOrValues` have rejected or cancelled.
+ * The resolution value will the first value of `promisesOrValues` to resolve.
###
any: ( promisesOrValues ) ->
- return @when( promisesOrValues ).then(
+ return @some( promisesOrValues, 1 ).then( success: ( values ) -> return values[ 0 ] )
+
+ ###*
+ * Initiates a competitive race, returning a new {@link Deft.promise.Promise} that will resolve when `howMany` of the supplied `promisesOrValues`
+ * have resolved, or will reject when it becomes impossible for `howMany` to resolve.
+ * The resolution value will be an Array of the first `howMany` values of `promisesOrValues` to resolve.
+ ###
+ some: ( promisesOrValues, howMany ) ->
+ return @when( promisesOrValues ).then(
success: ( promisesOrValues ) ->
- deferred = Ext.create( 'Deft.promise.Deferred' )
+ values = []
+ remainingToResolve = howMany
+ remainingToReject = ( promisesOrValues.length - remainingToResolve ) + 1
- updater = ( progress ) ->
- deferred.update( progress )
- return progress
- resolver = ( value ) ->
- complete()
- deferred.resolve( value )
- return value
- rejecter = ( error ) ->
- complete()
- deferred.reject( error )
- return error
- canceller = ( reason ) ->
- complete()
- deferred.cancel( reason )
- return reason
-
- complete = ->
- updater = resolver = rejecter = canceller = Ext.emptyFn
-
- successFunction = ( value ) -> resolver( value )
- failureFunction = ( value ) -> rejecter( value )
- progressFunction = ( value ) -> updater( value )
- cancelFunction = ( value ) -> canceller( value )
+ deferred = Ext.create( 'Deft.promise.Deferred' )
- for promiseOrValue, index in promisesOrValues
- if index of promisesOrValues
- @when( promiseOrValue )
- .then(
- success: successFunction
- failure: failureFunction
- progress: progressFunction
- cancel: cancelFunction
- )
+ if promisesOrValues.length < howMany
+ deferred.reject( new Error( 'Too few Promises or values were supplied to obtain the requested number of resolved values.' ) )
+ else
+ errorMessage = if howMany is 1 then 'No Promises were resolved.' else 'Too few Promises were resolved.'
+
+ updater = ( progress ) ->
+ deferred.update( progress )
+ return progress
+ resolver = ( value ) ->
+ values.push( value )
+ remainingToResolve--
+ if remainingToResolve is 0
+ complete()
+ deferred.resolve( values )
+ return value
+ rejecter = ( error ) ->
+ remainingToReject--
+ if remainingToReject is 0
+ complete()
+ deferred.reject( new Error( errorMessage ) )
+ return error
+ canceller = ( reason ) ->
+ remainingToReject--
+ if remainingToReject is 0
+ complete()
+ deferred.reject( new Error( errorMessage ) )
+ return reason
+
+ complete = ->
+ updater = resolver = rejecter = canceller = Ext.emptyFn
+
+ successFunction = ( value ) -> resolver( value )
+ failureFunction = ( value ) -> rejecter( value )
+ progressFunction = ( value ) -> updater( value )
+ cancelFunction = ( value ) -> canceller( value )
+
+ for promiseOrValue, index in promisesOrValues
+ if index of promisesOrValues
+ @when( promiseOrValue )
+ .then(
+ success: successFunction
+ failure: failureFunction
+ progress: progressFunction
+ cancel: cancelFunction
+ )
return deferred.getPromise()
scope: @
diff --git a/src/js/Deft/promise/Promise.js b/src/js/Deft/promise/Promise.js
index 19ff88a..02f5269 100644
--- a/src/js/Deft/promise/Promise.js
+++ b/src/js/Deft/promise/Promise.js
@@ -3,7 +3,7 @@
Copyright (c) 2012 [DeftJS Framework Contributors](http://deftjs.org)
Open source under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
-Promise.when(), all(), any(), map() and reduce() methods adapted from:
+Promise.when(), all(), any(), some(), map() and reduce() methods adapted from:
[when.js](https://github.com/cujojs/when)
Copyright (c) B Cavalier & J Hann
Open source under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
@@ -110,58 +110,90 @@ Ext.define('Deft.promise.Promise', {
});
},
/**
- * Returns a new {@link Deft.promise.Promise} that will only resolve once any one of the the specified `promisesOrValues` has resolved.
- * The resolution value will be the resolution value of the triggering `promiseOrValue`.
+ * Initiates a competitive race, returning a new {@link Deft.promise.Promise} that will resolve when any one of the supplied `promisesOrValues`
+ * have resolved, or will reject when all `promisesOrValues` have rejected or cancelled.
+ * The resolution value will the first value of `promisesOrValues` to resolve.
*/
any: function(promisesOrValues) {
+ return this.some(promisesOrValues, 1).then({
+ success: function(values) {
+ return values[0];
+ }
+ });
+ },
+ /**
+ * Initiates a competitive race, returning a new {@link Deft.promise.Promise} that will resolve when `howMany` of the supplied `promisesOrValues`
+ * have resolved, or will reject when it becomes impossible for `howMany` to resolve.
+ * The resolution value will be an Array of the first `howMany` values of `promisesOrValues` to resolve.
+ */
+
+ some: function(promisesOrValues, howMany) {
return this.when(promisesOrValues).then({
success: function(promisesOrValues) {
- var cancelFunction, canceller, complete, deferred, failureFunction, index, progressFunction, promiseOrValue, rejecter, resolver, successFunction, updater, _i, _len;
+ var cancelFunction, canceller, complete, deferred, errorMessage, failureFunction, index, progressFunction, promiseOrValue, rejecter, remainingToReject, remainingToResolve, resolver, successFunction, updater, values, _i, _len;
+ values = [];
+ remainingToResolve = howMany;
+ remainingToReject = (promisesOrValues.length - remainingToResolve) + 1;
deferred = Ext.create('Deft.promise.Deferred');
- updater = function(progress) {
- deferred.update(progress);
- return progress;
- };
- resolver = function(value) {
- complete();
- deferred.resolve(value);
- return value;
- };
- rejecter = function(error) {
- complete();
- deferred.reject(error);
- return error;
- };
- canceller = function(reason) {
- complete();
- deferred.cancel(reason);
- return reason;
- };
- complete = function() {
- return updater = resolver = rejecter = canceller = Ext.emptyFn;
- };
- successFunction = function(value) {
- return resolver(value);
- };
- failureFunction = function(value) {
- return rejecter(value);
- };
- progressFunction = function(value) {
- return updater(value);
- };
- cancelFunction = function(value) {
- return canceller(value);
- };
- for (index = _i = 0, _len = promisesOrValues.length; _i < _len; index = ++_i) {
- promiseOrValue = promisesOrValues[index];
- if (index in promisesOrValues) {
- this.when(promiseOrValue).then({
- success: successFunction,
- failure: failureFunction,
- progress: progressFunction,
- cancel: cancelFunction
- });
+ if (promisesOrValues.length < howMany) {
+ deferred.reject(new Error('Too few Promises or values were supplied to obtain the requested number of resolved values.'));
+ } else {
+ errorMessage = howMany === 1 ? 'No Promises were resolved.' : 'Too few Promises were resolved.';
+ updater = function(progress) {
+ deferred.update(progress);
+ return progress;
+ };
+ resolver = function(value) {
+ values.push(value);
+ remainingToResolve--;
+ if (remainingToResolve === 0) {
+ complete();
+ deferred.resolve(values);
+ }
+ return value;
+ };
+ rejecter = function(error) {
+ remainingToReject--;
+ if (remainingToReject === 0) {
+ complete();
+ deferred.reject(new Error(errorMessage));
+ }
+ return error;
+ };
+ canceller = function(reason) {
+ remainingToReject--;
+ if (remainingToReject === 0) {
+ complete();
+ deferred.reject(new Error(errorMessage));
+ }
+ return reason;
+ };
+ complete = function() {
+ return updater = resolver = rejecter = canceller = Ext.emptyFn;
+ };
+ successFunction = function(value) {
+ return resolver(value);
+ };
+ failureFunction = function(value) {
+ return rejecter(value);
+ };
+ progressFunction = function(value) {
+ return updater(value);
+ };
+ cancelFunction = function(value) {
+ return canceller(value);
+ };
+ for (index = _i = 0, _len = promisesOrValues.length; _i < _len; index = ++_i) {
+ promiseOrValue = promisesOrValues[index];
+ if (index in promisesOrValues) {
+ this.when(promiseOrValue).then({
+ success: successFunction,
+ failure: failureFunction,
+ progress: progressFunction,
+ cancel: cancelFunction
+ });
+ }
}
}
return deferred.getPromise();