jQuery-使用.done()、. then()和.when()以给定顺序发出Ajax请求

And*_*ndy 4 javascript ajax jquery

我一直在阅读有关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";
?>
Run Code Online (Sandbox Code Playgroud)

因此,如果这些被并行运行,顺序,他们会完成会r2.phpr3.phpr1.php

但是,如果我们想为了运行这些东西(r1.PHP, ,r2.php),r3.php并有jQuery的等待,直到每个AJAX请求之前就进入下一个做?例如,如果某物r2.php取决于r1.phpetc 的结果。

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

$(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);
           });

       });
   });
Run Code Online (Sandbox Code Playgroud)

});

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

在此处输入图片说明

此外,由于在该回调正在运行我可以访问,例如范围,response1(的输出r1.php在回调),该把手r3.php

在此处输入图片说明

我的问题是:在什么情况下实际上需要除此功能之外的任何功能.done()(例如.then().when()-在无数资源中提到的功能)?你什么时候甚至会需要.then()或者.when()对于这种类型的场景?

据我了解,它.done()是Promise兼容的。我什至在上面的代码中替换.done().then(),结果完全相同。

我已经阅读了以下所有内容,但我感觉所有这些都使如何使用jquery依次运行ajax请求的问题变得更加复杂:

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

我最初问的是这个问题,但我感觉措辞不好,没有包含足够的代码。因此,我模拟了此处给出的代码以说明确切的问题。

Jus*_*rce 5

.done()仅当Promise解析时才调用该方法(与之相对.fail(),当Promise被拒绝时将调用)。

.then()方法接受已解决的回调和被拒绝的回调,等效于一起使用完成/失败,例如:

$.ajax().then(resolvedCallback(), rejectedCallback());
Run Code Online (Sandbox Code Playgroud)

相当于

$.ajax().done(sucess()).fail(failure());
Run Code Online (Sandbox Code Playgroud)

不同之处在于,.then()可以更轻松地将多个链接在一起以实现更复杂的Promise分辨率。

.when()方法,可以在一个无极/递延/ Thenable封装了一些逻辑,这样就可以使用.then().done().fail()可以使用。如果您要执行一些复杂或长期运行的逻辑,并且需要轻松地将其包装在Promise / Deferred中,则这很有用。它还使阅读起来更容易:

$.when(function(){/*I do something that takes a while*/})
 .then(function(){/*I succeed*/},
       function(){/*I fail*/})
 .then( ... )
 .then( ... )
 ...
Run Code Online (Sandbox Code Playgroud)

然后,您可以终止链.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!');
 });
Run Code Online (Sandbox Code Playgroud)

在此示例中,fetchMe()$.ajax()调用中返回Promise 。使用时.when(),我们告诉脚本等待这三个脚本都完成,然后继续进行.then()。resolve方法的输入按递延项的顺序接收它们,.when()然后从那里可以从请求中检索数据。