延迟jquery的计时问题 [英] timing issues with jquery deferred

查看:162
本文介绍了延迟jquery的计时问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This question is carefully distilled version of not asynchronous function executed as jQuery Deferred.

我们有2个jsfiddles:

We have 2 jsfiddles:


  1. < a href =http://jsfiddle.net/XSDVX/1/ =nofollow noreferrer> http://jsfiddle.net/XSDVX/1/ - 这里的进展事件不会被解雇,尽管调用notify()函数。

  1. http://jsfiddle.net/XSDVX/1/ - here the progress event is not fired, despite calling notify() function.

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

http://jsfiddle.net/UXSbw/1/ - here the progress event is fired as expected.

唯一的区别是一行代码:

The only difference is one line of code:

setTimeout(dfd.resolve,1);

dfd.resolve();

问题是:



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


  • 我可以摆脱 setTimeout()并仍然有进度回调解雇?

  • Can I get rid of setTimeout() and still have progress callback fired?


    推荐答案

    制作了一个大型重构,这里是一个最后的工作示例,,包括进度监控。

    Made a big refactor and here is one final working example, with progress monitoring.

    现在重要的部分。


    • 在调用resolve之后,JQuery deferreds不执行任何进度回调(有一个例外)。在你的例子中(没有setTimeout),deferred立即被解决,没有机会运行进度。

    • 执行所有回调的钩子,特别是进度的回复,之前我们在最后的Deferred上触发enything。这是通过将最终的Deferred(现在的信标)传递给执行函数之后我们已经填充它的触发器来实现的。

    • 我重构了API,所以func为执行是延迟不可知的。

    • 此解决方案使用关闭本地的一个(减少迭代器函数)延迟,在memo.then函数内部,以便继续执行链。

    • JQuery deferreds do not execute any progress callbacks, after the resolve has been called (with one exception). In your example (without setTimeout), the deferred is immediately resolved, no chances to run progress.
    • Do the hooks of all callbacks, especially the progress ones, before we trigger enything on the final Deferred. This is achieved by passing the final Deferred (now beacon) to the execution function, after we have populated it's triggers.
    • I refactored the API so the func to be executed is deferred agnostic.
    • This solution, uses a closure of a local (to the reduce iterator function) Deferred, inside the memo.then function, in order to continue the execution chain.

    编辑:我忘记了你的第一个问题。
    此行为是通过
    结束(dfd变量)实现的在x函数中)。

    I forgot your first question. This behavior is achieved via the means of a closure (the dfd variable in the "x" function).

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

    The function "x" returns immediately (after triggering a notify event which now can be processed, as all the Deferreds of the execution chain have been created, and the done, fail, progress hooks of the "executePromiseQueueSync" have been hooked).

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

    Also the function of the setTimeout "closes" the dfd in a closure, so it can access the variable despite that the "x" has returned. The "then" call continues by creating the next deferred that is linked to the first one.

    JS VM产生后(它没有其他事情可做),setTimeout触发它的相关功能,(通过关闭)可以访问关闭dfd变量。延期已解决且链条可以继续。

    After the JS VM yields (it has not other things to do), the setTimeout triggers it's associated function, that (by the means of closure) have access to the "closed" dfd variable. The Deferred is resolved and the chain can continue.

    EDIT2:这是一个重构版本,它增加了对长期执行,延期支持函数的支持,它们会通知调用者他们的进度。

    Here is a refactored version that adds support for long executing, deferred supported functions, where they notify their caller for their progress.

    EDIT3:这是另一个版本,没有下划线绑定和jq-ui进度条示例。

    Here is another version, without underscore binding and with a jq-ui progressbar example.

    顺便说一句,这对于复杂的应用程序初始化例程来说是个好主意。

    By the way this is very good idea for complex app initialization routines.

    Source(第一个版本) )

    Source (of the first version)

    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)
    

    这篇关于延迟jquery的计时问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆