链接未知数量的AJAX请求

时间:2014-10-01 18:32:47

标签: jquery jquery-deferred

尽管我读过很多帖子,但我有点困惑......

我想将N AJAX请求链接到N >= 1N取决于第一个请求的响应,第一个请求和剩余请求之间存在依赖关系。我不想冻结浏览器。

由于用例有点复杂,我会尽量简化。想象一下,我们有一个API可以检索应用程序的所有用户和每个用户的个人地址。我想显示所有地址。像这样:

function doSomething() {

    var addresses = '';

    $.getJSON('/api/users', function(data) {
        $(data).each(function(id, user) {
            $.getJSON('/api/user/' + user.id + '/address', function(address) {
                addresses += address.displayName + '<br/>';
            });
        });
    });
    // do something with the addresses and display it somewhere
    $("#xxx").append(addresses);
}

最好的方法是什么?

2 个答案:

答案 0 :(得分:3)

以这种方式使用complete变量:

function doSomething() {

    var addresses = '';

    $.getJSON('/api/users', function(data) {
        var complete = 0;
        $(data).each(function(id, user) {
            $.getJSON('/api/user/' + user.id + '/address', function(address) {
                addresses += address.displayName + '<br/>';
                if (++complete !== data.length) { return; }
                // do something with the addresses and display it somewhere
                $("#xxx").append(addresses);
            });
        });
    });
}

此外,使用promises是另一种解决方案:

function doSomething() {

    var addresses = '';

    $.getJSON('/api/users', function(data) {
        var $allAjax = [];
        $(data).each(function(id, user) {
            $allAjax.push($.getJSON('/api/user/' + user.id + '/address', function(address) {
                addresses += address.displayName + '<br/>';
            }));
        });
        $.when.apply($, $allAjax).done(function () {
            // do something with the addresses and display it somewhere
            $("#xxx").append(addresses);
        });
    });
}

要保持地址顺序,您应该使用数组:

var addresses = [];

而不是+= address.displayName + "<br/>",你会这样做:

addresses[id] = address.displayName;

最后只需覆盖addresses变量:

addresses = addresses.join("<br/>");

答案 1 :(得分:0)

您可能会发现重构代码以提供getAddresses()函数更有用,它可以实现这一点 - 获取地址。该函数需要返回一个promise。

function getAddresses() {
    return $.getJSON('/api/users').then(function(data) {
        return $.when.appy(null, data.map(function(user) {
            return $.getJSON('/api/user/' + user.id + '/address');
        })).then(function () {
            //convert the function's arguments to an array of addresses
            return Array.prototype.slice.apply(arguments).map(function(a) {
                return a[0];//crazy but that's the way jQuery's ajax functions deliver their data
            });
        });
    });
}

现在,在调用getAddresses()的地方,可以使用地址执行某些操作:

var promiseOfAddresses = getAddresses().then(function(addresses) {
    // do something with the addresses and display it somewhere
    var displayNames = addresses.map(function(address) {
        return address.displayName;
    });
    $("#xxx").append(displayNames.join('<br/>'));
    return addresses;
});

promiseOfAddresses =分配对于回答问题并不是绝对必要的,但如果您需要对代码中的地址进行其他任何操作,这将非常有用。

promiseOfAddresses.then(function(addresses) {
    //do something else with the addresses here
});