关于javascript:jquery – 使用.done(),. then()和.when()以给定的顺序发出ajax请求

jquery - usage of .done(), .then() and .when() for making ajax requests in a given order

在编写多个ajax请求时,我一直在阅读jquery中的Promises并避免"回调地狱"。

我觉得即使在阅读了所有这些内容之后,就链接请求而言,在.done().then().when()方面没有给出使用什么的简单答案。

我试图构建最基本的例子来说明我的观点。下面的代码完全按照我的意愿工作,但唯一依赖的是.done(),我无法看到其他方法(例如.then().when())适合这个。

所以我创建了3个PHP脚本,并使用PHP的sleep方法人为地延迟了这些脚本完成的时间。延迟时间如下:

  • r1.php - 5秒
  • r2.php - 1秒
  • r3.php - 3秒

脚本本身就像这样简单:

1
2
3
4
5
6
7
8
<?php
    // r1.php
    echo"starting r1.php
"
;
    sleep(5); // Delay execution. Varies as described above for each script
    echo"ending r1.php
"
;
?>

因此,如果它们并行运行,那么它们完成的顺序将是r2.phpr3.php,然后是r1.php

但是如果我们想按顺序运行它们(r1 .php,r2.phpr3.php)并让jquery等到每个ajax请求进行到下一个之后呢?例如,如果r2.php中的某些内容取决于r1.php的结果等。

我写了以下内容 - 这正是如此:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$(document).ready(function() {
   $.ajax({
        url: 'ajax/r1.php',
        method: 'get'
   }).done(function(response1) {
       console.log('After r1.php
'
);
       console.log(response1);

       $.ajax({
            url: 'ajax/r2.php',
            method: 'get'
       }).done(function(response2) {
           console.log('After r2.php
'
);
           console.log('response1:' + response1);
           console.log(response2);

           $.ajax({
                url: 'ajax/r3.php',
                method: 'get'
           }).done(function(response3) {
               console.log('After r3.php
'
);
               console.log('response1:' + response1);
               console.log('response2:' + response2);
               console.log(response3);
           });

       });
   });

});

如您所见,请求按顺序完成,并占用每个PHP脚本中指定的时间:

enter image description here

此外,由于回调运行的范围,我可以访问处理r3.php的回调中的response1(r1.php的输出):

enter image description here

我的问题是:在什么情况下除.done()之外的任何函数(例如.then().when() - 在无数资源中提到的)实际上需要做这种类型的事情?什么时候你甚至需要.then().when()这种情况?

据我所知,.done()与Promise兼容。我甚至在上面的代码中用.then()替换了.done(),结果完全相同。

我已经阅读了以下所有内容,但我觉得所有这些都使问题复杂化,如何使用jquery按顺序运行ajax请求:

  • jQuery延迟和承诺 - .then()vs .done()
  • 如何使用jQuery promises链接三个异步调用?
  • https://medium.com/coding-design/writing-better-ajax-8ee4a7fb95f

有人可以用初学者可以理解的方式解释这个吗?我正在使用jquery 3.2.1所以想要一个特定于jquery的响应,而不是vanilla JavaScript。

我最初问过这个问题,但我觉得它措辞不好而且没有包含足够的代码。所以我嘲笑了这里给出的代码来说明确切的问题。


.done()方法仅在Promise解析时调用(与.fail()相反,后者在Promise被拒绝时调用)。

.then()方法接受已解析和拒绝的回调,相当于同时使用done / fail,这样:

1
$.ajax().then(resolvedCallback(), rejectedCallback());

相当于

1
$.ajax().done(sucess()).fail(failure());

不同之处在于,多个.then()可以更容易地链接在一起,以实现更复杂的Promise解析。

.when()方法允许您将一些逻辑封装在Promise / Deffered / Thenable中,以便可以使用.then().done().fail()。如果你想要执行一些复杂或长时间运行的逻辑并且需要将它包装在Promise / Deferred中,这很有用。它还使阅读更容易:

1
2
3
4
5
6
$.when(function(){/*I do something that takes a while*/})
 .then(function(){/*I succeed*/},
       function(){/*I fail*/})
 .then( ... )
 .then( ... )
 ...

然后,您可以在.always()中结束链以清除任何类型的结果或执行必须始终在链的末尾发生的某些操作,无论您的承诺是否已解决或被拒绝。

编辑:全部放在一起

使用.when(),我们可以让代码等待单元完成许多工作,然后继续:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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()中的顺序获取延迟项,从那里,我们可以从请求中检索数据。


您可以尝试$.Deffered链接多个ajax调用以使它们顺序。

  • 文档:HTTPS://api.jquery.com/category/deferred-object/
  • 类似的问题:如何使所有AJAX调用顺序?