使用递归函数按顺序执行多个 ajax 请求,并在所有请求完成后执行回调函数

Multiple ajax request in sequence using recursive function and execute callback function after all requests completed

本文关键字:执行 请求 函数 回调 顺序 ajax 递归函数      更新时间:2023-09-26

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

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

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

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

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]);

问题

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

要按顺序发出 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([]));
}

(更新的JSFIDDLE(


请注意,任务的要求中没有任何关于按顺序发出的 ajax 请求的内容。您也可以让它们并行运行并等待它们全部完成:

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);
    })
}

(更新的JSFIDDLE(

// global:
var pendingRequests = 0;
// after each ajax request:
pendingRequests++;
// inside the callback:
if (--pendingRequest == 0) {
    // all requests have completed
}

我已经将您的代码修改为最小以使其工作 - Click here .

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