javascript - jquery deferred 的时间问题

标签 javascript jquery race-condition jquery-deferred deferred

这个问题是 not asynchronous function executed as jQuery Deferred 的精心提炼版本.

我们有 2 个 jsfiddle:

  1. http://jsfiddle.net/XSDVX/1/ - 尽管调用了 notify() 函数,但此处未触发进度事件。

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

唯一的区别是一行代码:

setTimeout(dfd.resolve,1);

对比

dfd.resolve();

问题是:

  1. How is .then catching the .notify that is called before this callback returns when we delay the resolve? Think about it. .then takes the deferred object that was returned from it's first parameter and creates a new deferred object from it, binding to it's done progress and fail events. If the notify was called before the deferred was returned, how is .then catching it even with a setTimeout? (Thanks to https://stackoverflow.com/users/400654/kevin-b for asking this)

  2. 我可以去掉 setTimeout() 并仍然触发进度回调吗?

最佳答案

进行了重大重构,这里是 one final working example,带有进度监控。

现在是重要的部分。

  • JQuery deferreds 在 resolve 被调用后不执行任何进度回调(with one exception)。在您的示例中(没有 setTimeout),延迟立即解决,没有机会运行进度。
  • 执行所有回调的 Hook ,尤其是进度回调,我们在最终 Deferred 上触发任何事情之前。这是通过将最终的 Deferred(现在是信标)传递给执行函数来实现的,我们填充它的触发器之后。
  • 我重构了 API,因此要执行的函数是延迟不可知的。
  • 此解决方案使用 closure局部(到 reduce 迭代器函数)延迟,在 memo.then 函数内,以继续执行链。

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

函数“x”立即返回(在触发一个现在可以处理的通知事件后,因为执行链的所有 Deferred 都已创建,并且“executePromiseQueueSync”的完成、失败、进度钩子(Hook)已被钩住).

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

在 JS VM 产生(它没有其他事情可做)之后,setTimeout 触发它的关联函数,该函数(通过闭包)可以访问“已关闭”的 dfd 变量。 Deferred 已解决,链可以继续。

编辑 2:Here is a refactored version这增加了对长时间执行、延迟支持的函数的支持,它们会通知调用者它们的进度。

EDIT3:这是another version ,没有下划线绑定(bind)和一个 jq-ui progressbar 示例。

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

来源(第一个版本)

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)

关于javascript - jquery deferred 的时间问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15840865/

相关文章:

javascript - 如何使用jQuery将分页表格导出到excel

竞争条件下的循环

c# - 静态的线程安全

javascript - ExtJS:如何切换 html View

javascript - 获取特定表单的所有元素

javascript - 获取由nestable.js插件创建的嵌套列表中的li ID

ruby - 生成唯一代码时防止竞争条件

javascript - 在 Chrome 扩展程序中存储用户数据的选项

jquery - 互联网浏览器无法与精美盒子正常工作

javascript - 使用 jQuery 在我的 html 的 `onclick` 属性中获取函数的内容