小编典典

如何使用jQuery链接ajax调用

ajax

我需要发出一系列N ajax请求而不锁定浏览器,并且想要使用jquery延迟对象来完成此操作。

这是一个具有三个请求的简化示例,但是我的程序可能需要排队100个以上(请注意,这不是确切的用例,实际代码的确需要在执行下一个步骤之前确保步骤(N-1)的成功步):

$(document).ready(function(){

    var deferred = $.Deferred();

    var countries = ["US", "CA", "MX"];

    $.each(countries, function(index, country){

        deferred.pipe(getData(country));

    });

 });

function getData(country){

    var data = {
        "country": country  
    };


    console.log("Making request for [" + country + "]");

    return $.ajax({
        type: "POST",
        url: "ajax.jsp",
        data: data,
        dataType: "JSON",
        success: function(){
            console.log("Successful request for [" + country + "]");
        }
    });

}

这是写入控制台的内容(所有请求都是并行进行的,响应时间与预期的每个国家/地区的数据大小成正比:

Making request for [US]
Making request for [CA]
Making request for [MX]
Successful request for [MX]
Successful request for [CA]
Successful request for [US]

我怎样才能让延期的对象为我排队呢?我试过更改完成管道,但得到相同的结果。

这是期望的结果:

Making request for [US]
Successful request for [US]
Making request for [CA]
Successful request for [CA]
Making request for [MX]
Successful request for [MX]

编辑:

我很欣赏使用数组存储请求参数的建议,但是jquery延迟对象具有将请求排队的能力,我真的想学习如何充分利用此功能。

这实际上是我想要做的:

when(request[0]).pipe(request[1]).pipe(request[2])... pipe(request[N]);

但是,我想一次将请求分配到管道中一次,以便有效地使用每个遍历:

deferred.pipe(request[0]);
deferred.pipe(request[1]);
deferred.pipe(request[2]);

阅读 283

收藏
2020-07-26

共1个答案

小编典典

带有自定义对象

function DeferredAjax(opts) {
    this.options=opts;
    this.deferred=$.Deferred();
    this.country=opts.country;
}
DeferredAjax.prototype.invoke=function() {
    var self=this, data={country:self.country};
    console.log("Making request for [" + self.country + "]");

    return $.ajax({
        type: "GET",
        url: "wait.php",
        data: data,
        dataType: "JSON",
        success: function(){
            console.log("Successful request for [" + self.country + "]");
            self.deferred.resolve();
        }
    });
};
DeferredAjax.prototype.promise=function() {
    return this.deferred.promise();
};


var countries = ["US", "CA", "MX"], startingpoint = $.Deferred();
startingpoint.resolve();

$.each(countries, function(ix, country) {
    var da = new DeferredAjax({
        country: country
    });
    $.when(startingpoint ).then(function() {
        da.invoke();
    });
    startingpoint= da;
});

小提琴http://jsfiddle.net/7kuX9/1/

为了更清楚一点,可以写最后几行

c1=new DeferredAjax( {country:"US"} );
c2=new DeferredAjax( {country:"CA"} );
c3=new DeferredAjax( {country:"MX"} );

$.when( c1 ).then( function() {c2.invoke();} );
$.when( c2 ).then( function() {c3.invoke();} );

带管道

function fireRequest(country) {
        return $.ajax({
            type: "GET",
            url: "wait.php",
            data: {country:country},
            dataType: "JSON",
            success: function(){
                console.log("Successful request for [" + country + "]");
            }
        });
}

var countries=["US","CA","MX"], startingpoint=$.Deferred();
startingpoint.resolve();

$.each(countries,function(ix,country) {
    startingpoint=startingpoint.pipe( function() {
        console.log("Making request for [" + country + "]");
        return fireRequest(country);
    });
});

http://jsfiddle.net/k8aUj/1/

编辑:在结果窗口中输出日志的小提琴http://jsfiddle.net/k8aUj/3/

每个管道调用都返回一个新的Promise,该诺言又用于下一个管道。请注意,我仅提供了sccess功能,应该为失败提供类似的功能。

在每种解决方案中,通过将Ajax调用包装到一个函数中来延迟它们,直到需要使用为止,并为列表中的每个项目创建一个新的Promise以构建链。

我相信自定义对象提供了一种操作链的简便方法,但是管道可以更好地适合您的口味。

注意 :从jQuery
1.8开始,deferred.pipe()不推荐使用,deferred.then将其替换。

2020-07-26