等待ajax在下一次ajax调用之前完成

时间:2014-05-17 19:45:40

标签: javascript jquery ajax recursion promise

我正在尝试等待ajax调用以在保存列表中的下一个模型之前完成模型的保存。我正在谷歌上搜索一些关于延迟对象的东西,对我来说是新的,另一个有递归函数的答案就是这样做的。我尝试了递归方法,因为它似乎比使用延迟对象和使用$.when.apply($, arrayOfAjaxCalls).then()更有意义。所以代码(递归的,看起来像:

    saveModel(index, numRequests) {
        var self = this;

        if (index < numRequests) {
            var sample = self.samplesToSave[index];    

            return $.ajax({
                url: model.url,
                contentType: "application/json",
                type: "POST",
                data: JSON.stringify(model),
                crossDomain: $.support.cors,
                xhrFields: {
                    withCredentials: $.support.cors,
                },
                success: function(data) {
                    console.log("JUST SAVED");
                    console.log(data);
                },
                error: function(xhr: any) {
                    console.log(xhr);
                },
            }).then(() => {
                self.saveModel(index + 1, numRequests);
            });
        }
    }

我称之为:

saveModel(0, _.size(myCollection)

在调用下一个saveModel之前,它实际上并没有等待ajax调用以其当前状态结束。它基本上只是按顺序同步调用集合中每个项目的saveModel。对我缺少什么的想法?如果使用$ .Deferred有一个更好的解决方案,我也可以。感谢。

编辑:对不起,这意味着在saveModel函数的最后一行说saveModel。试图摆脱属于特定领域的部分。我正在使用打字稿,而不是coffeescript

新尝试:

    saveSampleNew() {
        var d = $.Deferred();
        d.resolve();
        var p = d.promise();
        var self = this;
        self.samplesToSave.forEach(sample => p = p.then(() => self.makeSaveRequest(sample)));

        return p;
    }

     makeSaveRequest(sample) {
        var self = this;

        return $.ajax({
            url:  "samples",
            contentType: "application/json",
            type: "POST",
            data: JSON.stringify(sample),
            crossDomain: $.support.cors,
            xhrFields: {
                withCredentials: $.support.cors,
            },
            success: function(data) {
                console.log("SAVED12");
                console.log(data);                    
            },
        });
    }

因为此代码依赖于完成的其他异步调用,所以我将这样的新尝试称为:

this.saveContainers(project).then(() => {

}).done(() => {
    self.saveSampleNew();
});

2 个答案:

答案 0 :(得分:1)

不,它应该以这种方式工作。如果您认为它不会等待,请提供有关您如何调用它以及它如何同步递归的经验的更多信息。

然而,递归调用有一个问题:

.then(function() {
  self.saveModel(index + 1, numRequests);
})

then返回的promise以及随后的saveModel方法返回的promise确实直接解析了第一个ajax调用,它不会等待递归链。其他ajax调用仍在发生(按预​​期顺序执行),但未被结果承诺跟踪。

为了得到这个,并正确地承诺,以便它与最后一个(&#34;最里面的&#34;)承诺的结果一起解析,你需要return从回调到then

的承诺
.then(function() {
  return self.saveModel(index + 1, numRequests);
})

答案 1 :(得分:0)

我可能在这里使用for循环而不是递归调用,通常 - 我发现在这种情况下更容易阅读。

saveModel() {
     var d = $.Deferred(); d.resolve();
     var p = d.promise(); // to start the chain
     this.samplesToSave.forEach(sample => p = p.then(() => makeSaveRequest(sample));
     return p;
}

makeSaveRequest(sample) {
    return $.ajax({...}); // make request using `sample` as data
}