同步jquery $ .ajax没有锁定IE?

时间:2012-04-20 08:55:53

标签: jquery ajax asynchronous

花了一点时间试图实现这个并且有一个我觉得在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;
}

2 个答案:

答案 0 :(得分:1)

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

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)

答案 1 :(得分:1)

我认为我问题的最佳答案是......你做错了。我没有按照建议的那样运气(也许是因为我理解它),所以我自己想出了以下答案。

基本上,使用回调来实现一种递归排队。对你们所有人来说这听起来很明显,但对我来说这是新手,我认为那里经验丰富的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,它跟踪请求数组,加载此itteration的特定索引,以及调用方法时添加的seriesData。 Anon方法成功用于构建我的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调用的人。谢谢!