延迟jquery的计时问题

这个问题是经过精心提炼的非异步函数版本, 作为jQuery Deferred执行 。

我们有2个jsfiddles:

  1. http://jsfiddle.net/XSDVX/1/ – 尽管调用了notify()函数,但不会触发progress事件。

  2. http://jsfiddle.net/UXSbw/1/ – 这里按预期触发进度事件。

唯一的区别是一行代码:

setTimeout(dfd.resolve,1); 

 dfd.resolve(); 

问题是:

  1. 当我们延迟解决时,如何捕获在此回调返回之前调用的.notify? 想一想。 .then获取从它的第一个参数返回的延迟对象,并从中创建一个新的延迟对象,绑定到它完成的进度和失败事件。 如果在返回deferred之前调用了notify,那么即使使用setTimeout,它是如何捕获它的? (感谢https://stackoverflow.com/users/400654/kevin-b询问此问题)

  2. 我可以摆脱setTimeout()并仍然有进程回调被解雇?

制作了一个大型重构,这是一个最后的工作示例,具有进度监控function。

现在重要的部分。

  • 在调用resolve之后,JQuery deferreds不会执行任何进度回调( 有一个例外 )。 在您的示例中(没有setTimeout),延迟会立即解决,无法运行进度。
  • 我们触发最终延期的enything 之前 ,做所有回调的钩子,尤其是进度回调。 这是通过我们填充它的触发器之后将最终的Deferred(现在的beacon)传递给执行函数来实现的。
  • 我重构了API,因此要执行的func是延迟不可知的。
  • 这个解决方案,在memo.then函数内部使用一个本地的闭包 (to reduce iterator function)Deferred,以便继续执行链。

编辑:我忘记了你的第一个问题。 这种行为是通过闭包的方式实现的(“x”函数中的dfd变量)。

函数“x”立即返回(在触发现在可以处理的通知事件之后,因为已经创建了执行链的所有延迟,并且已经挂起了“executePromiseQueueSync”的完成,失败,进度挂钩)。

此外,setTimeout的函数“关闭”闭包中的dfd,因此它可以访问变量,尽管“x”已经返回。 “then”调用通过创建链接到第一个延迟的下一个延迟来继续。

在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)