我一直在阅读有关jquery中的Promises的文章,并在发出多个ajax请求时避免了“回调地狱”。
即使在阅读了所有这些内容之后,我仍然觉得并没有给出简单的答案-使用.done()
,.then()
和.when()
-链接请求
我试图构建最基本的示例来说明我的观点。下面的代码完全按照我想要的方式工作,但是它唯一依赖的是.done()
,而且我看不到其他方法(例如.then()
或.when()
)适合的位置这个。
因此,我创建了3个PHP脚本,并使用PHP的sleep方法人为地延迟了这些脚本完成所需的时间。延迟设置如下:
r1.php
-5秒r2.php
-1秒r3.php
-3秒脚本本身就是这样简单:
<?php
// r1.php
echo "starting r1.php \n";
sleep(5); // Delay execution. Varies as described above for each script
echo "ending r1.php \n";
?>
因此,如果并行运行这些命令,则完成的顺序将是r2.php
,r3.php
,然后是r1.php
。
但是,如果我们想按顺序运行它们(r1
。php,r2.php
,r3.php
)并让jquery等到每个ajax请求都发出后再继续下一个怎么办? ?例如,如果r2.php
中的某物取决于r1.php
等的结果。
我写了以下内容-正是这样:
$(document).ready(function() {
$.ajax({
url: 'ajax/r1.php',
method: 'get'
}).done(function(response1) {
console.log('After r1.php\n');
console.log(response1);
$.ajax({
url: 'ajax/r2.php',
method: 'get'
}).done(function(response2) {
console.log('After r2.php\n');
console.log('response1:' + response1);
console.log(response2);
$.ajax({
url: 'ajax/r3.php',
method: 'get'
}).done(function(response3) {
console.log('After r3.php\n');
console.log('response1:' + response1);
console.log('response2:' + response2);
console.log(response3);
});
});
});
});
如您所见,请求按顺序完成,并花费每个PHP脚本中指定的时间:
此外,由于回调的运行范围,我可以在处理response1
的回调中访问r1.php
(r3.php
的输出):>
我的问题是:在什么情况下除.done()
以外的任何功能(例如.then()
或.when()
-在无数资源中都提到)实际上需要做这种事情吗?这种情况下您什么时候甚至需要.then()
或.when()
?
据我了解,.done()
是Promise兼容的。在上面的代码中,我什至用.done()
替换了.then()
,结果完全一样。
我已经阅读了以下所有内容,但我感觉所有这些都使如何用jquery依次运行ajax请求的问题变得更加复杂:
请有人可以用初学者可以理解的方式来解释吗?我正在使用 jquery 3.2.1 ,所以想要一个特定于jquery的响应,而不是原始JavaScript。
我最初询问的是this question,但我觉得它的措词不好,没有包含足够的代码。因此,我模拟了此处给出的代码以说明确切的问题。
答案 0 :(得分:5)
.done()
方法仅在Promise解析时才调用(与.fail()
相对,在Promise被拒绝时调用)。
.then()
方法接受已解决和被拒绝的回调,等效于一起使用完成/失败,例如:
$.ajax().then(resolvedCallback(), rejectedCallback());
等同于
$.ajax().done(sucess()).fail(failure());
区别在于,多个.then()
可以更容易地链接在一起,以实现更复杂的Promise分辨率。
.when()
方法允许您将一些逻辑封装在Promise / Deffered / Thenable中,以便您可以使用.then()
,.done()
和.fail()
。如果您要执行一些复杂或长期运行的逻辑,并且需要轻松地将其包装在Promise / Deferred中,则这很有用。它还使阅读更容易:
$.when(function(){/*I do something that takes a while*/})
.then(function(){/*I succeed*/},
function(){/*I fail*/})
.then( ... )
.then( ... )
...
然后,您可以在.always()
中终止链以清理任何类型的结果或执行某些必须始终在链末尾执行的操作,而不管您的诺言是否得到了解决或被拒绝。
编辑:将它们放在一起
使用.when()
,我们可以让代码等待单元完成一些事情,然后再继续:
function fetchMe(url) {
return $.ajax({
url: url,
method: 'get'
});
}
$.when(fetchMe('ajax/r1.php'), fetchMe('ajax/r2.php'), fetchMe('ajax/r3.php'))
.then(function(r1, r2, r3) { // Resolve
console.log('response1: ' + r1.data);
console.log('response2: ' + r2.data);
console.log('response3: ' + r3.data);
}, function(){ // Reject!
console.log('Something broke!');
});
在此示例中,fetchMe()
从$.ajax()
调用中返回Promise。使用.when()
,我们告诉脚本在完成.then()
之前等待所有这三个条件完成。 resolve方法的输入按.when()
中的顺序接收延迟的项目,然后从那里可以从请求中检索数据。
答案 1 :(得分:-1)
您可以尝试$.Deffered
链接多个ajax调用以使其顺序执行。