jQuery $.Deferred实现批量AJAX按顺序执行等待完成问题求助
问题原因
你当前的循环是同步遍历所有选中ID并直接触发doExport,所有AJAX请求会同时发起,才会出现先打印全部starting日志的情况。要实现串行执行,需要把每个操作通过Promise链式调用串联,保证前一个请求完成后再触发下一个。
代码修改方案
首先doExport函数可以简化(可选,因为$.ajax本身就返回DeferredPromise,不需要额外包装一层):
// 简化后的doExport function doExport(id) { return $.ajax({ type: "POST", url: "import.php", dataType: "json", data: { id: id } }); }
然后修改importInvoices的遍历逻辑,用reduce构建串行Promise链:
function importInvoices() { var checked = []; $('#apiCall').html(""); // 收集选中ID $("input[name=selectedRow]:checked").each(function(num,row) { checked.push($(row).data('id')); }); // 构建串行Promise链 checked.reduce(function(prevPromise, currentId) { // 上一个请求完成后再执行下一个 return prevPromise.then(function() { console.log("starting " + currentId); return doExport(currentId).then(function(result) { console.log("done " + currentId); $('#apiCall').html($("#apiCall").html() + result.messages); }); }); }, $.Deferred().resolve()) // 初始用已完成的Promise作为起点 .then(function() { // 所有请求都完成后再隐藏加载提示 $("#pleaseWaitContainer").hide(); }); }
逻辑说明
reduce会把所有异步操作按顺序拼接成链式调用,每一步的执行都依赖上一步的完成- 初始传入已经resolve的Deferred对象,保证第一个请求可以正常触发
- 原来同步执行的
$("#pleaseWaitContainer").hide()移动到整个Promise链的最终回调中,避免请求还在执行就提前隐藏加载提示
修改后运行就能得到你预期的日志输出顺序,操作消息的展示顺序也能保证正确。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

