$.ajax inside $.each 阻塞浏览器

$.ajax inside $.each blocking browser

我有这样的事情:遍历 ID 并针对每个 ID 向服务器(同一域)发出 ajax 请求(async:true)并将接收到的数据附加到 DOM 元素。这不是一项艰巨的任务,它确实有效。示例代码:

$.each(ids, function (index, id) {
    $.ajax({
        type: 'POST',
        url: "http://localhost/example/"+id,
        success: function (data) {
            $('#content').append(data);
        }
    });
});

我的问题是:当我需要循环访问很多 ID(例如 1000 个)时,它会发送很多 ajax,而浏览器 "freeze",当我点击一个 link,它等待所有 ajax 请求完成,然后打开点击的 link。

超时不是一个选项,因为我需要显示尽可能多的接收数据。如果需要 1 秒或 100 秒才能完成,这没有问题,因为用户会看到其他已完成的请求

那么,处理这个问题的最佳方法是什么?当像 this 这样的 link 被点击时停止 ajax 请求?或者有更好的方法

更好的方法是更改​​请求数据的方式。

如果可能,请尝试将服务器更改为接受多个 ID,并一次使用所有 ID 发出一个请求。这样,您将遍历数据而不是 AJAX 请求。

想一想。对于 1000 个 ID 的数组,每次您点击该功能时,您至少会发出 1001 个请求(页面 1 个!)。如果该请求由数据库支持,则为 1000 个单独的数据库命中。

现代网络浏览器只会处理如此多的并发 AJAX 请求,然后才会将其余请求排队等待稍后处理。您提供的代码可能没有提高性能的好方法。

无需对应用程序进行 1000 ajax 次调用,您可以让服务器 return json 格式

[{ id: 0, content: "A",
id: 1, content: "B",
.
.
id: n, content: "Nth content" }]

这样的请求
var idList = [];
$.each(ids, function(index, id) {
    idList.push(id);
});
$.ajax({
type: "POST",
data: { id: idList },
success: function(data) {
    $.each(data, function(index, v) {
        $("#content").append(v.content);
    })
}).error(function(response) {
    $("#content").append(response);
});

Chrome 据我所知一次可以处理 8 个并发 ajax 请求,像 1000 这样的数字对它来说太多了。上面的代码会将 ajax 调用的次数从 1000 减少到 1。

但是,如果您确实想像这样进行 1000 次调用,那么您最好这样做

var idList = [];
$.each(ids, function(index, id) {
    idList.push(id);
});
function makeAjax() {
    $.ajax({
        type: "POST"
        data: { id : idList.pop()},
        success: function(data) {
            $("#content").append(data);
        }
    }).done(function() {
        if(idList.length>0) {
            makeAjax();
        }
    });
}

下面的代码一次最多产生 8 个 ajax 调用。

var idList = [];
$.each(ids, function(index, id) {
    idList.push(id);
});
var MAX_THREADS = 8;
var CURRENT_THREADS = 0;

function makeAjax() {
    CURRENT_THREADS++;
    $.ajax({
        type: "POST"
        data: { id : idList.pop()},
        success: function(data) {
            $("#content").append(data);
        }
    }).done(function() {
        CURRENT_THREADS--;
    });
}

function callAjax() {
    if(CURRENT_THREADS < MAX_THREADS) {
        makeAjax();
    }
    if(idList.length > 0) {
        setTimeout(callAjax, 1000);
    }
}

callAjax();

不过我不建议这样做。如果一次获取所有 ID 的内容需要很长时间,您最好使用其他一些解决方案,例如分页。