javascript - How to make sure $.each pushes all deferreds in jQuery? -
i have following jquery code:
myfunc: function(cmd, obj){ var idtoextmap = this. map; var requireres = this.reqinst; var deferreds = []; var ret = true; $.each(idtoextmap[cmd], function(key, ext){ if(ext.$classins && ext.$classins.prepare) { var returnedvalue = ext.$classins.prepare(obj); deferreds.push(returnedvalue); $.when(returnedvalue).done(function(satisfied){ if(ret!==false){ ret = satisfied; } }); } else { requireres(ext).done(function(){ var cls = $.tofunction(ext.$jscls); if(cls) { ext.$classins = new cls(); if(ext.$classins.prepare){ var returnedvalue = ext.$classins.prepare(obj); deferreds.push(returnedvalue); $.when(returnedvalue).done(function(satisfied){ if(ret!==false){ ret = satisfied; } }); } } }); } }); $.when.apply(null, deferreds).done(function(){ return ret; }); }
the problem having $.when.apply executed before deferreds pushed deferreds array. how can make sure $.when.apply executed once deferreds pushed deferreds array?
the main thing have ensure promises pushed onto array synchronously. deferreds.push(...)
burried inside done callback, push()
asynchronous , array guaranteed still empty when $.when.apply(...)
executed.
some other issues can fixed :
- code repetition around
ext.$classins.prepare(obj)
can avoided rearrangement. - the cumbersome outer var
ret
can avoided exploiting promise rejection.
with other minor tidying, ended (untested) :
myfunc: function(cmd, obj) { var requireres = this.reqinst; var promises = $.map(this.map[cmd], function(key, ext) { var p; // p promise if(ext.$classins) { p = $.when(ext.$classins); } else { p = requireres(ext).then(function() { var cls = $.tofunction(ext.$jscls); if(cls) { ext.$classins = new cls(); } return ext.$classins || null; }); } /* @ point, `p` promise resolved either created `cls()` object or freshly created 1 */ // inside `$.map(...)`, `return p.then(...)` causes promise delivered `p.then(...)` pushed onto `promises` array. return p.then(function($classins) { if($classins && $classins.prepare) { return $classins.prepare(obj).then(function(satisfied) { if(!satisfied) { // here, returning rejected promise equivalent setting original `ret` irrevocably `false`. return $.deferred().reject(new error(".prepare() not satisfied")); } }); } else { // may want reject if `$classins` or `$classins.prepare` doesn't exist. // if not, delete else{} clause. return $.deferred().reject(new error(".prepare() not called")); } }); }); /* @ point, `promises` array of promises - or resolved, or pending */ // here, instead of boolean `ret`, can exploit joined promise's success/error paths : // * success path equivalent ret == true. // * error path equivalent ret == false, or unpredicted error. return $.when.apply(null, promises).then(function() { // success. // whatever necessary here or in `myfunc().then(function() {...})`. }, function(e) { // error occurred. // whatever necessary here or in `myfunc().then(null, function() {...})`. console.error(e); //for example }); }
comments should explain what's going on.
Comments
Post a Comment