我有一个标准的
JavaScript对象,其原型通过.start()方法扩展,分别以2个回调作为参数:success和failure.此方法执行一些异步处理(它不是AJAX),并且根据该处理的结果,它调用成功或失败回调.
以下是如何进行图解的:
function MyObject() { } MyObject.prototype.start = function(successCallback,errorCallback) { (function(s,e) { window.setTimeout(function() { if (Math.random() < 0.8) { s(); } else { e(); } },2000); })(successCallback,errorCallback); }
在方法中执行的精确处理并不重要,只是它是异步和非阻塞.我无法控制start方法完成处理的时间点.我也无法控制这种方法的原型和实现.
我所控制的是成功和失败的回调.由我来提供它们.
现在我有一个数组的这些对象:
var arr = [ new MyObject(),new MyObject(),new MyObject() ];
这个数组中元素的顺序很重要.我需要连续地触发数组的每个元素上的.start()方法,但是只有一次前一个完成(即调用成功回调).并且如果发生错误(调用失败回调),我想停止执行,并且不再对数组的其余元素调用.start方法.
我可以通过使用递归函数来实现这一点:
function doProcessing(array,index) { array[index++].start(function() { console.log('finished processing the ' + index + ' element'); if (index < array.length) { doProcessing(array,index); } },function() { console.log('some error ocurred'); }); } doProcessing(arr,0);
这很好,但是看看在jQuery 1.5中引入的jQuery’s deferred Object我认为这个代码有改进的余地.不幸的是,我感觉不舒服,我正在尝试学习.
所以我的问题是可以调整我的天真的代码,并利用这个新的API,如果是的,你能给我一些指针吗?
这是一个jsfiddle与我的实现.
解决方法
你可以这样做:(
jsFiddle)
function MyObject() { } MyObject.prototype.start = function(queue) { var deferred = $.Deferred(); //only execute this when everything else in the queue has finished and succeeded $.when.apply(jQuery,queue).done(function() { window.setTimeout(function() { if (Math.random() < 0.8) { deferred.resolve(); } else { deferred.reject(); } },2000); }); return deferred; } var arr = [ new MyObject(),new MyObject() ]; var queue = new Array(); $.each(arr,function(index,value) { queue.push(value.start(queue) .done(function() { console.log('succeeded ' + index); }) .fail(function() { console.log('Failed ' + index); })); });
不太确定你会认为这是一个改进,但是.