使用 jQuery 的动态 AJAX 承诺链

Posted

技术标签:

【中文标题】使用 jQuery 的动态 AJAX 承诺链【英文标题】:Dynamic AJAX promise chain with jQuery 【发布时间】:2014-05-09 07:10:41 【问题描述】:

我的 AJAX 调用是在 for 循环中构建的。它们需要有序(同步)。如何用 jQuery 链接它们?

var array = ['One', 'Two', 'Three'];
var arrayLength = array.length;
for (var arrayCounter = 0; arrayCounter < arrayLength; arrayCounter++) 
    var id = array[arrayCounter];
    getData(id);

    function getData(id) 
        $.ajax(
            url: 'http://example.com/' + id,
            dataType: 'jsonp',
            success: function(d) 
                var response = d;
                console.log(d);
            ,
            error: function() 
                alert("ERROR");
            
        );
    
   

【问题讨论】:

【参考方案1】:

大多数promise库都内置了这个,用jQuery?没那么幸运:

首先,你的函数应该返回一个承诺:

 function getData(id) 
        return $.ajax( // note the return
            url: 'http://example.com/'+id,
            dataType: 'jsonp',
            success: function (d) 
                console.log(d);
            ,
            error: function () 
                alert("ERROR")
            
        );

现在,您使用.then 调用将它们链接在一个循环中。请注意,.then 只会在前一个承诺完成后执行。所以他们都会按顺序运行,一个接一个。

var array = ['One', 'Two', 'Three'];
var p = $.when(1); // empty promise
array.forEach(function(el)
    p = p.then(function()
        return getData(el);;
    );
);

所有功能将一个接一个地运行。还剩下什么?返回值。当前实现丢弃返回值。我们可以将返回值放在一个数组中,例如:

var array = ['One', 'Two', 'Three'];
var p = $.when(1); // empty promise
var results = [];
array.forEach(function(el,index)
    p = p.then(function()
        return getData(el);
    ).then(function(data)
        results[index] = data; // save the data
    );
);
p.then(function()
    // all promises done, results contains the return values
);

为什么要停在那里,让我们让它变得更好:) 你的整个代码可以缩短为

["One","Two","Three"].map(makeUrl).map($.get).reduce(function(prev,cur,idx)
    return prev.then(cur).then(function(data) results[idx] = data; );
,$.when(1)).then(function()
   // results contains all responses here, all requests are sync
);

function makeUrl(id)
    return "http://example.com"+id+"?callback=?";

【讨论】:

你真的用过“缩短”这个词吗? 是的,我相信我做到了。【参考方案2】:

使用for的解决方案:

var array = ['One', 'Two', 'Three'];
var id = array[0];
var data = getData(id);
for (var i = 1; i < array.length; i++) 
    // Or only the last "i" will be used
    (function (i) 
        data = data.then(function() 
            return getData(array[i]);
        );
    (i));


// Also, see how better the getData can be.
function getData(id) 
    return $.ajax(
        url: 'http://example.com/' + id,
        dataType: 'jsonp',
    ).done(function(d) 
        var response = d;
        console.log(d);
    ).fail(function() 
        alert('ERROR');
    );

顺便说一句,如果您使用了适当的 Promise 库,例如 bluebird,您将使用以下代码:

var array = ['One', 'Two', 'Three'];
Promise.reduce(array, function(data, id) 
    return data.promise.then(function(result) 
        return  promise: getData(id), results: data.results.push(result) ;
    );
, []).then(function(data) 
    console.log(data.results); // yay!
);

function getData(id) 
    return Promise.cast($.ajax(
        url: 'http://example.com/' + id,
        dataType: 'jsonp',
    ).done(function(d) 
        var response = d;
        console.log(d);
    ).fail(function() 
        alert('ERROR');
    ));

如您所见,更容易读/写。

【讨论】:

以上是关于使用 jQuery 的动态 AJAX 承诺链的主要内容,如果未能解决你的问题,请参考以下文章

如何动态地向promises链添加新的承诺

jQuery Deferred - 等待多个 AJAX 请求完成 [重复]

使用 jQuery 解决循环中的承诺 [重复]

jQuery使用ajax跨域请求获取数据

Jquery ajax json 不执行success的原因 坑爹

HTTP 错误 405.0 - 不允许使用 Jquery ajax get 的方法