【问题标题】:Multiple ajax request in sequence using recursive function and execute callback function after all requests completed使用递归函数顺序多个ajax请求并在所有请求完成后执行回调函数
【发布时间】:2014-12-16 07:46:21
【问题描述】:

我有用逗号分隔的名称列表。我想要的是我想为序列中的所有名称调用服务器请求并将结果存储在数组中。我试过了,当我确实有字符串中有多个名称时它正在工作。

Here - 当我知道名字的数量时,这是有效的

现在我想要的是我想让这段代码通用。如果我在该字符串中添加一个名称,它应该会自动处理,而无需为 ajax 请求添加任何代码。

Here - 这是我尝试过的。它没有按预期工作。

shoppingList = shoppingList.split(",");
var result = [];

function fetchData(shoppingItem)
{
    var s1 = $.ajax('/items/'+shoppingItem);
    s1.then(function(res) {
        result.push(new Item(res.label,res.price));
        console.log("works fine");
    });
    if(shoppingList.length == 0)
    {
        completeCallback(result);
    }
    else
    {
        fetchData(shoppingList.splice(0,1)[0]);
    }
}

fetchData(shoppingList.splice(0,1)[0]);

问题

我不知道如何检测所有承诺对象已被解析,以便我可以调用回调函数。

【问题讨论】:

标签: javascript ajax recursion


【解决方案1】:

要按顺序发出ajax请求,您必须将递归调用放在回调中:

function fetchList(shoppingList, completeCallback) {
    var result = [];
    function fetchData() {
        if (shoppingList.length == 0) {
            completeCallback(result);
        } else {
            $.ajax('/items/'+shoppingList.shift()).then(function(res) {
                result.push(new Item(res.label,res.price));
                console.log("works fine");
                fetchData();
//              ^^^^^^^^^^^
            });
        }
    }
    fetchData();
}

或者你实际上使用了承诺并做

function fetchList(shoppingList) {
    return shoppingList.reduce(function(resultPromise, shoppingItem) {
        return resultPromise.then(function(result) {
            return $.ajax('/items/'+shoppingItem).then(function(res) {
                result.push(new Item(res.label,res.price));
                return result;
            });
        });
    }, $.when([]));
}

(updated jsfiddle)


请注意,任务要求中没有关于按顺序发出 ajax 请求的内容。你也可以让它们并行运行,wait for all of them to finish:

function fetchList(shoppingList) {
    $.when.apply($, shoppingList.map(function(shoppingItem) {
        return $.ajax('/items/'+shoppingItem).then(function(res) {
            return new Item(res.label,res.price);
        });
    })).then(function() {
        return Array.prototype.slice.call(arguments);
    })
}

(updated jsfiddle)

【讨论】:

  • 它看起来是正确的,但我发现它很难理解。您能否更新我的小提琴代码以便我理解。我想使用第二种方法。
【解决方案2】:
// global:
var pendingRequests = 0;

// after each ajax request:
pendingRequests++;

// inside the callback:
if (--pendingRequest == 0) {
    // all requests have completed
}

【讨论】:

  • 这和我做的检查数组长度一样。我认为这不会有帮助。你能更新我的小提琴并告诉我它是如何工作的吗?
【解决方案3】:

我已将您的代码修改为最少以使其正常工作 - Click here

请注意,您的最后一个断言将失败,因为项目承诺未以线性方式解决。因此项目的顺序会改变。

【讨论】:

    猜你喜欢
    • 2011-08-12
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-28
    • 2016-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多