【问题标题】:Dynamic AJAX promise chain with jQuery使用 jQuery 的动态 AJAX 承诺链
【发布时间】: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");
            }
        });
    }
}   

【问题讨论】:

    标签: javascript jquery ajax promise chaining


    【解决方案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');
        }));
    }
    

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

    【讨论】:

      猜你喜欢
      • 2012-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-14
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多