使用 jQuery deferred 中止 AJAX 请求链
Posted
技术标签:
【中文标题】使用 jQuery deferred 中止 AJAX 请求链【英文标题】:Abort chain of AJAX requests with jQuery deferred 【发布时间】:2018-06-22 02:50:43 【问题描述】:我正在进行一系列 AJAX 调用,如下例所示,我在 http://www.dotnetcurry.com/jquery/1022/jquery-ajax-deferred-promises 找到了它。
如果 function A 中 AJAX 调用的响应是空 JSON 对象数组(即“[ ]”)?理想情况下,我不仅要中止 AJAX 调用链,还要通知用户没有找到结果。
谢谢!
function A()
writeMessage("Calling Function A");
return $.ajax(
url: "/scripts/S9/1.json",
type: "GET",
dataType: "json"
);
function B(resultFromA)
writeMessage("In Function B. Result From A = " + resultFromA.data);
return $.ajax(
url: "/scripts/S9/2.json",
type: "GET",
dataType: "json"
);
function C(resultFromB)
writeMessage("In Function C. Result From B = " + resultFromB.data);
return $.ajax(
url: "/scripts/S9/3.json",
type: "GET",
dataType: "json"
);
function D(resultFromC)
writeMessage("In Function D. Result From C = " + resultFromC.data);
A().then(B).then(C).then(D);
function writeMessage(msg)
$("#para").append(msg + "<br>");
【问题讨论】:
【参考方案1】:通常,您可以让每个工作函数 A、B、C、D 返回一个对象,该对象包含响应数据以及您是否要继续调用链中的下一个函数,无论它可能是什么。像这样的:
function A(input)
return $.get("/scripts/S9/1.json").then(function (response)
return
continue: response.data && response.data.length,
data: response
;
);
现在您可以通过减少一组工作函数来创建一个承诺链,并在每个步骤中决定您是否要继续(在这种情况下您执行下一个工作程序)或不(您只需继续返回最后一个有效的链的其余部分的结果)。由于没有更好的名称,我已将此逻辑包装到函数 breakableChain
中。
function maybe() return Math.random() > 0.25;
function A(input) console.log('in A:', input.data); return continue: maybe(), data: 'result from A';
function B(input) console.log('in B:', input.data); return continue: maybe(), data: 'result from B';
function C(input) console.log('in C:', input.data); return continue: maybe(), data: 'result from C';
function D(input) console.log('in D:', input.data); return continue: maybe(), data: 'result from D';
function breakableChain(workers, init)
return workers.reduce(function (current, next)
return current.then(function (result)
return result.continue ? next(result) : result;
);
, $.Deferred().resolve(continue: true, data: init));
breakableChain([A, B, C, D], 'initial data').then(function (result)
console.log('overall:', result.data);
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
当然,您可以制作一个不需要continue
标志的非通用版本,而是将关于每个结果的假设直接硬编码到.reduce()
内的if
语句中。那会更短,但不能重复使用。
整个continue: true, data: result
只是一个约定。您的约定也可以是“如果先前的调用返回任何内容,则继续,否则停止”,方法相同,但无法返回整体结果。
【讨论】:
感谢@Tomalak 花时间写出如此详细的答案!不幸的是,第二块中的许多概念对我来说并不熟悉。我不明白该代码,所以我不知道如何应用它。我需要第二个代码块吗? 顺便问一下,你知道一个很好的资源来学习你在第二个代码块中使用的东西吗? 当然您需要第二个代码块,它可以完成所有工作。这是我的答案的核心。我理解如果你不能完全理解它,它需要对异步代码如何工作,特别是 Promises 如何工作有扎实的了解。我怀疑您也不太了解自己的代码示例。这对我来说很难解决。 我建议您阅读有关 Promises 的内容。从字面上看,几乎无限的博客文章、教程、文档(如 MDN)、关于它们是什么以及它们如何工作的各个方面的详细 Stack Overflow 答案。有了这些,你就会对什么是异步代码有所了解。如果这些概念对您来说是新的,那肯定需要一点时间,但是没有办法做到这一点。一旦您对自己的代码示例有了更好的理解,就可以集中精力对其进行渐进式更改。我的代码不是解决您问题的唯一方法,但希望随着时间的推移它会变得更加清晰。 再次感谢@Tomalak。我实际上确实理解我提到的代码示例。我从不使用我不理解的代码。我会阅读承诺,并希望最终能理解你的答案:D 我很感激你的回答。以上是关于使用 jQuery deferred 中止 AJAX 请求链的主要内容,如果未能解决你的问题,请参考以下文章