3

花了一些时间试图实现这一点,并有一个我认为在 Firefox 中运行良好的解决方案,但是在 IE 中进行测试时发现使用 async: false 会导致浏览器被锁定(停止响应并似乎已冻结)通话时长。

要求基本如下。我提供了一系列用户可以检查的复选框。在特定时间,我调用我的函数“selectedSeriesData()”,该函数用于一个接一个地向我的服务发送请求,获取请求的数据。我特别选择使用同步,以便在方法执行时向浏览器输出状态消息和警告。

例如。“加载数据 1/3”,然后“加载数据 2/3”,“加载数据 3/3”

当然,我现在知道这会锁定某些浏览器,因此 IE 中的体验不仅会锁定浏览器,而且我尝试显示的任何消息都不会显示。是否有任何简单的 doEvents 之类的动作,我可以在每次 ajax 调用后调用,或者只是重组我的 ajax 调用的问题。如果是这样的话,根据我的要求有什么实施建议吗?

以下是代码的简化摘录以供参考。

function selectedSeriesData() {

    var seriesData = [];
    var index = 0;

    $.each($("input[name='idCheckBox']:checked"), function () {

        var id = $(this).val();

        $("#loadingMessage").text("Loading " + id + "...");

            $.ajax({
                type: 'POST',
                async: false,
                url: '<%: loadSeriesDataPath %>',
                dataType: 'json',
                data: {
                    Id: id
                },
                success: function (data) {
                    seriesData[index] = data;
                    index++;
                },
                error: function (xhr, ajaxOptions, error) {
                    $("#warnings ul").append('<li>A communication error occured while attempting to load data for the series.</li>');

                }
            });
        }
    });
    return seriesData;
}
4

2 回答 2

1

您可以使用jQuery Deferred 对象继续使用异步请求,然后在所有请求完成后“加入”结果。

function selectedSeriesData(cb) {
    var reqs = [];
    $("#loadingMessage").text("Loading...");
    $("input[name='idCheckBox']:checked").each(function () {
        var id = $(this).val();

        var req = $.ajax({
            type: 'POST',
            url: '<%: loadSeriesDataPath %>',
            dataType: 'json',
            data: {
                Id: id
            },
            error: function(xhr, ajaxOptions, error) {
                $("#warnings ul").append('<li>A communication error occured while attempting to load data for the series.</li>');

            }
        });
        reqs.push(req);
    });
    $.when(reqs).done(function() {
        cb($.makeArray(arguments));
    });
}

现在,您只需将回调传递给您的函数,该函数将在所有成功完成后立即接收包含来自 AJAX 请求的所有结果的数组。

注意:$.when关于它是否接受包含延迟的单个数组的文档并不清楚。如果它不起作用,请尝试$.when.apply($, reqs)代替$.when(reqs)

于 2012-04-20T09:10:33.400 回答
1

我认为我的问题的最佳答案是......你做错了。正如建议的那样,我对 $.when 没有任何运气(也许是由于我对它的理解),所以我自己想出了以下答案。

基本上,使用回调来实现一种递归排队。这对你们所有人来说可能听起来很明显,但对我来说是新的,我认为那里有经验的 jqueryer 会同意我的实现(如果我做得对,请告诉我!)

首先,不是循环通过我的复选框并发出 ajax 请求,而是建立一个请求数组。这消除了从原始方法返回结果的需要,并开始了一系列方法执行,最终导致所需的结果。

function selectedSeriesData() {

    var requests = [];

    $.each($("input[name='somethingCheckBox']:checked"), function () {

        var id = $(this).attr('value');

        var request = {
            id: id
        };

        requests.push(request);

    });

    loadRequests(requests);
}

从请求数组中,开始调用 loadRequests,它初始化递归回调实现以从我的服务加载数据。

function loadRequests(requests)
{
    $("#loader").show();
    var seriesData = [];
    loadRequestAt(requests, 0, seriesData);
}

调用的递归方法是 loadRequestAt,它跟踪请求数组、加载此迭代的特定索引以及在调用方法时添加的 seriesData。Anon 方法 Success 用于构建我的 seriesData,Error 用于报告错误,而 Complete 最重要的是用于开始下一次请求迭代,或者如果所有请求都已发出,则将结果呈现到屏幕上。

function loadRequestAt(requests, loadAtIndex, seriesData) {
    var currentRequest = requests[loadAtIndex];

    $("#loadingMessage").text("Loading " + currentRequest.id + "...");

    $.ajax({
        type: 'POST',
        url: '<%: loadSeriesDataPath %>',
        dataType: 'json',
        data: {
            Id: currentRequest.id
        },
        success: function(data) {
            seriesData.push(data);
        },
        error: function(xhr, ajaxOptions, error) {
            $("#warnings ul").append('<li>A communication error occured while attempting to load ' + currentRequest.id'.</li>');
        },
        complete: function() {
            var nextIndex = loadAtIndex + 1;
            if (nextIndex < requests.length) {
                loadRequestAt(requests, nextIndex, seriesData);
            } else {
                $("#loader").hide();
                renderResults(seriesData);
            }
        }
    });
}

重要的经验教训。使用 AJAX(异步 JavaScript 和 XML)时,请务必使用异步调用。一定要使用提供的匿名回调方法来实现渐进式排队功能(我确定有一个可接受的名称,但我不确定)。希望我的学习步骤可以帮助那些不熟悉 jquery 和 ajax 调用的人。谢谢!

于 2012-04-20T16:32:29.127 回答