这个问题是精心蒸馏版本的jQuery的递延不执行异步函数 。
我们有2个jsfiddles:
http://jsfiddle.net/XSDVX/1/ -这里的进度事件不会触发,尽管调用通知()函数。
http://jsfiddle.net/UXSbw/1/ -在这里按预期进度事件。
唯一的区别是一行代码:
setTimeout(dfd.resolve,1);
与
dfd.resolve();
问题是:
。那么如何追赶,当我们拖延解决被这个回调返回之前叫.notify? 想想吧。 。然后将取得在返回从它的第一个参数的递延对象,并从它创建一个新的Deferred对象,结合它的完成进度和失败事件。 如果通知调用之前延期归还,怎么连。然后用setTimeout的追赶呢? (感谢https://stackoverflow.com/users/400654/kevin-b提出这项)
我可以摆脱setTimeout()
仍然有进步的回调解雇?
做了一个大重构,这里是一个最终的工作示例,以监测进展情况。
现在的重要组成部分。
- JQuery的deferreds不执行任何进展回调,决心一直被称为(后有一个例外 )。 在您的例子(没有的setTimeout),递延立即解决,没有机会跑的进展。
- 是否所有回调的挂钩,尤其是那些进步,我们触发enything最终延期了 。 这是通过最后的递延(现在灯塔)的执行功能, 经过我们填充它的触发器来实现的。
- 我重构的API,因此要执行的func被推迟无关。
- 该解决方案,使用一个封闭件递延本地的(到减少迭代器功能)时,memo.then函数内,以便继续执行链。
编辑:我忘了你的第一个问题。 此行为通过的手段实现封闭 (在“x”函数的DFD变量)。
功能的“x”立即返回(触发通知它现在可被处理,作为执行链的所有Deferreds已创建的事件后,将完成的,失败,进步“executePromiseQueueSync”的挂钩已经被钩住)。
另外,setTimeout的功能“关闭”在封闭的DFD,所以尽管该“X”又回到它可以访问的变量。 该“然后”呼叫继续创造下一个递延链接到第一个。
在JS VM收益率(有没有其他的事情要做)后,setTimeout的触发它相关的功能,即(由封闭的方式)有机会获得“封闭” DFD变量。 递延得到解决,链条可以继续。
EDIT2: 这里是一个重构版本 ,增加了长期执行,延期支持的功能,在那里他们通知其调用者为他们的进步的支持。
EDIT3:下面是另外一个版本 ,没有下划线结合,并用JQ-UI进度的例子。
顺便说一句,这是对于复杂应用程序的初始化程序非常好的主意。
源(第一版)
function executePromiseQueueSync(queue, beacon){
var seed = $.Deferred(),
le = queue.length,
last;
beacon.notify(0);
last = _.reduce(queue, function(memo, ent, ind){
var df = $.Deferred();
df.then(function(){
console.log("DBG proggie");
beacon.notify((ind+1)/le*100);
});
console.log("DBG hook funk "+ind);
memo.then(function(){
console.log("DBG exec func "+ind);
ent.funct.apply(null, ent.argmnt);
df.resolve();
});
return df.promise();
}, seed.promise());
last.then(function(){
beacon.resolve(100)
});
seed.resolve(); // trigger
return beacon.promise();
}
function x(){
// do stuff
console.log("blah");
}
var promisesQueue = [],
beacon = $.Deferred();
promisesQueue.push({funct: x, argmnt:[]});
promisesQueue.push({funct: x, argmnt:[]});
promisesQueue.push({funct: x, argmnt:[]});
function monTheProg(pct)
{
console.log('progress '+pct);
}
// first hook, then exec
beacon.then(function(){
console.log('success');
}, function(){
console.log('failure');
}, monTheProg);
// do the dance
executePromiseQueueSync(promisesQueue, beacon)