【问题标题】:Call function when the last one has finished最后一个完成时调用函数
【发布时间】:2016-12-29 16:38:09
【问题描述】:

我敢肯定,这个问题之前似乎已经被问过很多次了,但这不是典型的异步 JS 问题“如何仅在另一个函数完成时才调用函数?”。

所以我的场景如下:我需要使用 AJAX 加载一组相当繁重的数据,即按比赛周安排的比赛列表。我设置了一系列承诺,当它们都完成后,一旦我在 DOM 中获得了所有匹配项,我就会做其他事情。我有这样的事情:

var promises = [];
for (var i = 1; var i <= lastWeek; i++)
  promises.push($.ajax({
    url: "week/" + i,
    success: { ... }
  }));

$.when.apply($, promises).done(someFunction);

但是我注意到这会立即触发所有请求,并且可能会阻塞服务器端的进程并通常会出现故障。所以我想我会以不同的方式处理这个问题,而不是一次提出所有这些请求,我在第一周提出一个,一旦完成,我会提出以下要求,依此类推:

function loadWeek(week, last) {
  $.get("week/" + i, function (response) {
    // do whatever with the response
    // make the request for the next week
    if (week + 1 <= last)
      loadWeek(week + 1, last);
  });
}

现在我当然不能使用$.when,因为承诺是在前一个完成时动态生成的。

我想知道 JS 或 jQuery 是否提供了一种方法来在上周加载后向someFunction 函数(只有在加载所有匹配项后才应调用的函数)发出信号。

当然,你可以说,只要在week + 1 &gt; last 时调用它,对吗?好吧,我仍然需要使用 Promise,因为这个 someFunction 不仅需要等待这些匹配项被加载,还需要等待另一个 Promise 完成。

所以当我说我这样做时,你可以说我撒了一点谎:

$.when.apply($, promises).done(someFunction);

实际上,promises 实际上除了匹配列表之外还有更多的函数调用,而someFunction 应该有直到所有都完成。

【问题讨论】:

  • 也许是 jQuery .finish(function(){ //do somthing... }); ?
  • 你怎么知道他们什么时候完成的?我的意思是,标准是什么?具体长度?
  • @Syntac “全部”是什么意思?如果您在谈论匹配列表,那么当week 大于last 并且我们在success 块中时,匹配列表就完成了。至于其他人,我们知道他们已经完成,因为这是一个承诺。
  • 边问:如果原始版本一次发送所有请求并阻塞服务器,这是由于服务器上的资源限制吗?如果是这样,您是否希望将来有多个用户,即使您确实收到了来自单个用户的请求,他们仍然有能力一次触发一个用户?

标签: javascript jquery ajax


【解决方案1】:

好的,让我们分解一下,如果我理解正确,您想要以下内容

A- 按顺序加载几周

function loadWeek(week, last) {
    var deferred = $.Deferred();

    (function request(week, last) {
        $.get("week/" + i, function (response) {
            // do whatever with the response
            // make the request for the next week
            if (week + 1 <= last)
                request(week + 1, last);
            else
               deferred.resolve();
        });
    })(week, last);

    return deferred.promise();
}

B- 同时加载其他内容

function otherStuff() {
    // return some promise
}

C- 当 A 和 B 完成后调用 someFunction

var promises = []
promises.push(loadWeek(1, 10));
promises.push(otherStuff(...));
$.when.apply($, promises).done(someFunction);

【讨论】:

  • 你的想法是对的。但不要认为这会起作用,因为第一个 loadWeek 承诺将被视为完成,而不是最后一个。
  • 第一个和最后一个是什么意思?除非我没有遇到问题,否则这应该很有效
  • @dabadaba loadWeek 只被调用一次
  • 不,不是,它是递归调用的;只有最后一次调用应该是进程完成的信号
  • 仔细检查代码..函数request被递归调用..不是loadWeek..requestloadWeek内部定义的函数
【解决方案2】:

有多种方法,但最简单的方法之一是对您的尝试进行一些小调整(请参阅***):

function loadWeek(week, last, done) {      // ***
  $.get("week/" + i, function (response) {
    // do whatever with the response
    // make the request for the next week
    if (week + 1 <= last) {
      loadWeek(week + 1, last, done);      // ***
    } else {                               // ***
      done();                              // ***
    }                                      // ***
  });
}

然后只将 other 承诺推送到 promises(不是来自上述 loadWeek 的承诺),并且:

loadWeek(1, lastWeek, function() {
    $.when.apply($, promises).then(someFunction);
});

【讨论】:

  • 我仍然不明白这与必须等待其他承诺的需要如何工作。
  • @dabadaba:大部分代码都是你的。 :-) 当您调用loadWeek 时,它会进行 one ajax 调用,然后等待该调用完成;当它完成时,如果还有一周的时间加载,它会开始下一个loadWeek 调用。我们等待它完成,依此类推;最终,我们没有几周的时间来加载,所以我们调用done(在我上面的示例调用中是someFunction)。所以只有一个 ajax 调用在进行中,someFunction(在那个例子中)只有在最后一个完成时才会被调用。
  • 对。但这还不是全部。我提到这很棘手,因为不仅涉及异步加载这些匹配的过程,而且还有一些额外的 AJAX 调用需要done/someFunction 等待。在这里,您在加载上周后直接致电done,但这不是我所追求的。是的,我正在尝试在上周加载后调用done,但是在promises 数组中的所有函数都完成之后也是(我重复一遍,这个数组包含没有任何内容的其他函数与加载我们的比赛有关)
  • @dabadaba:只需结合这些方法:只推送你需要在数组中等待的承诺,而不是loadWeek,然后而不是直接调用done,所以@987654338 @ (或者在someFunction 中做同样的事情,这就是我可能会做的——更小的部分一起工作)。
  • 我想我现在明白了。但是这种方法不是意味着promises 中的函数只会在上周加载后调用吗?我不一定需要那个,但我想它也没有伤害。
【解决方案3】:

你想要一个在 Promise 时运行的函数,并且一个函数完成。小解决方法:

 var c=0;
 function callbyboth(){
 c++;
 if(c==2){
  //both executed
  //run your code
 }
 }

在你的承诺上添加这个

Promise.then(callbyboth);

在递归函数处:

if(week+1>=last){
  callbyboth();
}else{
 //recursion
}

【讨论】:

  • 我完全不明白你在这里想要达到什么目的。
  • 您说 TJCrowders 解决方案不起作用,因为您有更多的 Promise 并希望它们全部完成。上面的代码是一种变通方法,它只是计算函数被调用的次数,所以如果你有两个要等待的 promise/callbacks,则函数等待被调用两次
猜你喜欢
  • 2011-06-27
  • 1970-01-01
  • 2018-07-10
  • 1970-01-01
  • 2018-02-24
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多