最后一个完成后调用函数

时间:2016-12-29 16:38:10

标签: javascript jquery ajax

我确信看起来这个问题之前已经被问了很多,但这不是典型的异步JS问题“如何在另一个完成时调用函数?”。

所以我的场景如下:我需要使用AJAX加载一组非常繁重的数据,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 > last对话时调用它?好吧,我仍然需要使用promises,因为这个someFunction不仅需要等待加载这些匹配,还需要完成另一个承诺。

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

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

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

3 个答案:

答案 0 :(得分: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);

答案 1 :(得分:0)

有几种方法,但最简单的方法之一是对您的尝试进行小幅调整(参见***):

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();                              // ***
    }                                      // ***
  });
}

然后只将其他承诺推送到promises(而不是上面loadWeek的承诺),并且:

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

答案 2 :(得分:0)

您需要一个在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
}