同步jquery $ .ajax没有锁定IE?
花了一点时间试图实现这个并且有一个我觉得在firefox中工作得很好的解决方案,但是当在IE中测试发现使用async:false导致浏览器被锁定(停止响应并且已经冻结)通话时间。
要求基本如下。 我提供了一系列用户可以检查的复选框。 在特定时间,我调用我的函数’selectedSeriesData()’,该函数用于向我的服务一个接一个地发送请求以获取所请求的数据。 我特别选择使用sync,以便在执行方法时可以向浏览器输出状态消息和警告。
例如。 “加载数据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: '', dataType: 'json', data: { Id: id }, success: function (data) { seriesData[index] = data; index++; }, error: function (xhr, ajaxOptions, error) { $("#warnings ul").append('A communication error occured while attempting to load data for the series. '); } }); } }); return seriesData; }
您可以使用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('A communication error occured while attempting to load data for the series. '); } }); reqs.push(req); }); $.when(reqs).done(function() { cb($.makeArray(arguments)); }); }
现在您只需将回调传递给您的函数,然后只要所有结果都成功完成,它就会收到一个包含AJAX请求所有结果的数组。
注意: $.when
上的文档并不是很清楚它是否接受包含延迟的单个数组。 万一它不起作用尝试$.when.apply($, reqs)
而不是$.when.apply($, reqs)
$.when(reqs)
我认为我问题的最佳答案是……你做错了。 我没有任何运气与$ .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,它跟踪请求数组,加载此itteration的特定索引,以及调用方法时添加的seriesData。 匿名方法成功用于构建我的seriesData,用于报告错误的错误,以及用于开始下一次请求迭代的完成,或者如果已完成所有请求,则将结果呈现给屏幕。
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('A communication error occured while attempting to load ' + currentRequest.id'. '); }, complete: function() { var nextIndex = loadAtIndex + 1; if (nextIndex < requests.length) { loadRequestAt(requests, nextIndex, seriesData); } else { $("#loader").hide(); renderResults(seriesData); } } }); }
重要经验教训。 使用AJAX(异步JavaScript和XML)时,请使用异步调用。 请使用提供的匿名回调方法来实现渐进式排队function(我确信有一个可接受的名称,但我不确定)。 希望我的学习步骤能帮助那些不熟悉jquery和ajax调用的人。 谢谢!