代码之家  ›  专栏  ›  技术社区  ›  Andy

jquery-使用.done()、.then()和.when()按给定顺序发出ajax请求

  •  4
  • Andy  · 技术社区  · 7 年前

    我已经阅读了很多关于jquery中承诺的内容,并且在发出多个ajax请求时避免了“回调地狱”。

    我觉得,即使在阅读了所有这些之后,也没有一个简单的答案可以用来解释 .done() .then() .when() -在链接请求方面。

    我试着用最基本的例子来说明我的观点。下面的代码完全按照我的要求工作,但它唯一依赖的是 .完成() .然后() )适合这个。

    所以我创建了3个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";
    ?>
    

    所以如果这些是并行运行的,它们完成的顺序是 , ,然后 r1.菲律宾比索 .

    r1 .php, , r3.php语言 )jquery是否要等到每个ajax请求都发出之后再进行下一个?例如,如果 r2.php文件 r1.菲律宾比索 等。

    我已经写了以下内容-正是这样做的:

    $(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脚本中指定的时间:

    enter image description here

    此外,由于回调运行的范围,我可以访问,例如, response1 r1.菲律宾比索 )在处理 :

    enter image description here

    在什么情况下除了 .完成() .然后() -在无数的参考资料中提到了哪些)实际上需要做这种事情?你什么时候需要 .然后() 。当() 对于这种情况?

    据我所知, 承诺是一致的。我甚至换了 .完成() .然后() 在上面的代码中,结果是完全相同的。

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

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

    this question 但我觉得它的措辞很糟糕,没有包含足够的代码。所以我模拟了这里给出的代码来说明确切的问题。

    2 回复  |  直到 7 年前
        1
  •  6
  •   Justin Pearce    7 年前

    这个 .done() 方法只在Promise解析时调用(与 .fail() ,当承诺被拒绝时调用)。

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

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

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

    不同之处在于 可以更容易地链接在一起,以获得更复杂的承诺解决方案。

    这个 .when() 方法允许您将某些逻辑封装在Promise/defered/Thenable中,以便可以使用 .然后() , ,和 .失败() 可以使用。如果您想要执行一些复杂的或长时间运行的逻辑,并且需要轻松地将其包装在Promise/Deferred中,那么这非常有用。它还使阅读更容易:

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

    .always() 不管你的承诺是否得到解决或被拒绝,都要清理掉任何一种结果,或是采取一些行动,而这些行动必须始终发生在你的链条的末端。

    编辑:综合起来

    使用 。当()

    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() 打电话来。使用 ,我们告诉脚本在继续执行 .然后() . resolve方法的输入按照延迟项在 从那里,我们可以从请求中检索数据。

        2
  •  -2
  •   Simranjit Singh    7 年前

    $.Deffered 链接多个ajax调用以使它们按顺序进行。