【问题标题】:Making multi callback synchronized with jQuery $.when使多回调与 jQuery $.when 同步
【发布时间】:2015-02-15 22:05:35
【问题描述】:

这是我的示例代码:

function out(msg)
{
  $('#output').append(msg + '<br>');
}

var myDeferred = [];
$.each([8, 3, 4, 6, 9, 15, 7, 1], function (index, time)
{
  myDeferred.push($.Deferred(function(dfd)
  {
    setTimeout(function ()
    {
      out(time);
      dfd.resolve();
    }, time * 1000);
  }).promise());
});

$.when.apply($, myDeferred).then(function ()
{
  out('all is done');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"></div>

这个输出“1 3 4 6 7 8 9 15 all is done”,同时调用所有回调。

但我要“8 3 4 6 9 15 7 1 all is done”,所有回调一个接一个地调用。

有人可以帮助我吗?

提前致谢

【问题讨论】:

  • 你能澄清你想要什么吗?你想要 8 秒过去,打印一条消息,然后 3 秒过去,打印一条消息,...?
  • 你是什么意思“所有的回调被同时调用”——它们有不同的time 值和不同的超时时间?
  • @JuniorCompressor 你有一个很好的答案,但是 $.Deferred 有可能吗?
  • @Bergi 当我这么说时,我说的是数组 myDeferred 中的回调,而不是 setTimeout 上的回调
  • 如果您确实希望显示延迟,请不要在数组上使用$.when,而是在每个$Defered 上单独使用它。不完全清楚你的期望是什么

标签: javascript jquery asynchronous synchronization jquery-deferred


【解决方案1】:

问题是每个回调超时几乎同时被激活。不过,您可以执行以下操作:

function out(msg)
{
  $('#output').append(msg + '<br>');
}

function foo(index, callback) {
  var time = array[index];
  out(time);
  if (index == array.length - 1)
    callback();
  else
    setTimeout(foo, time * 1000, index + 1, callback);
}

var array = [8, 3, 4, 6, 9, 15, 7, 1];
foo(0, function ()
{
  out('all is done');
});

使用承诺:

function out(msg)
{
  $('#output').append(msg + '<br>');
}

var myDeferred = [];
$.each([8, 3, 4, 6, 9, 15, 7, 1], function (index, time)
{
  myDeferred.push($.Deferred(function(dfd)
  {
    var f = function() {
      out(time);
      dfd.resolve();
    }
    if (index > 0)
      myDeferred[index - 1].done(function() { setTimeout(f, time * 1000); });
    else 
      setTimeout(f, time * 1000);
  }).promise());
});

$.when.apply($, myDeferred).then(function ()
{
  out('all is done');
});

【讨论】:

  • 违背了尝试使用承诺的目的,这似乎是 OP 试图掌握的。在 ajax 情况下,不能保证数据会以与请求相同的顺序返回
  • 另外,此解决方案需要在启动新的解决方案之前完成先前的过程,这样需要更长的时间
  • 是的,但我认为这是@dtcSearch 的要求
  • 这是我的答案,只是,@JuniorCompressor 更接近我的演示?有可能吗?
  • @charlietfl 这不是速度问题,它是一个演示代码,我在 indexedDB 多插入的情况下使用它(因为不会同时用多插入阻塞客户端浏览器)
【解决方案2】:

不是在初始循环中记录您的响应,而是将您的数据传递给resolve(),然后在when() 中,您将收到已解析数据的数组。而是遍历该数组,一切都会井井有条

var myDeferred = [];
$.each([8, 3, 4, 6, 9, 15, 7, 1], function (index, time)
{
  myDeferred.push($.Deferred(function(dfd)
  {
    setTimeout(function ()
    {
      /* pass data to resolve()*/
      dfd.resolve(time);
    }, time * 100);
  }).promise());
});

$.when.apply($, myDeferred).then(function ()
{
    /* loop over arguments */
    $.each(arguments,function(_, time){
        out(time);
    });
    console.log(arguments);
    out('all is done');
});

DEMO

【讨论】:

  • 我希望不要同时调用数组 myDeferred 上的回调,在这里,这只是正确顺序的结果,但我会更多地谈论这样做的方法。感谢这个演示,你解决了(带参数)我的另一个问题,但不是这个
  • 那么根据开始时间 0 ,你到底想要发生什么?
猜你喜欢
  • 2013-01-18
  • 2017-03-19
  • 2013-03-09
  • 2015-01-11
  • 2017-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多