zoukankan      html  css  js  c++  java
  • jquery when,then,done(二)

    http://blog.csdn.net/aitangyong/article/details/47066395

    之前的文章"javascript异步代码的回调地狱"中提到了编写AJAX代码经常遇到的3个问题,现在我们看下如何利用then()解决第2个问题:如果AJAX请求之间存在依赖关系,我们的代码就会形成Pyramid of Doom(金字塔厄运)。比如我们要完成这样一件事:有4个供Ajax访问的url地址,需要先Ajax访问第1个,在第1个访问完成后,用拿到的返回数据作为参数再访问第2个,第2个访问完成后再第3个...以此到4个全部访问完成。按照这样的写法,似乎会变成这样:

    [javascript] view plain copy
     
    1. $.ajax({    
    2.     url: url1,    
    3.     success: function(data){    
    4.         $.ajax({    
    5.             url: url2,    
    6.             data: data,    
    7.             success: function(data){    
    8.                 $.ajax({    
    9.                     //...    
    10.                 });    
    11.             }        
    12.         });    
    13.     }    
    14. });  


    1.Deferred.then()相当于Deferred.done()、Deferred.fail()、Deferred.progress()的合体,可以同时注册3个状态下的回调函数。

    [javascript] view plain copy
     
    1. function success(data)  
    2. {  
    3.     alert("success data = " + data);  
    4. }  
    5.   
    6. function fail(data)  
    7. {  
    8.     alert("fail data = " + data);  
    9. }  
    10.   
    11. function progress(data)  
    12. {  
    13.     alert("progress data = " + data);  
    14. }  
    15.   
    16. var deferred = $.Deferred();  
    17.   
    18. // 一起注册回调  
    19. deferred.then(success, fail, progress);  
    20.   
    21. // 分别注册回调  
    22. deferred.done(success);  
    23. deferred.fail(fail);  
    24. deferred.progress(progress);  
    25.   
    26. deferred.notify("10%");  
    27. deferred.resolve("ok");    

    当然我们也可以像done()一样,多次调用then()注册回调函数。then()虽然可以这么使用,但是实际开发中一般不这么用,因为没有啥必要。JQuery1.8之前,这就是then()方法的作用。

    2.Deferred.then()解决多个异步操作之间有依赖的问题,这才是then()真正有意义的场景。JQuery1.8之后,then()取代了过时的pipe()方法。这种场景下,我们需要使用Deferred.then()返回的新Promise对象。上面的第一种使用方式,我们忽略了Deferred.then()的返回值。

    [javascript] view plain copy
     
    1. var deferred = $.Deferred();  
    2.   
    3. // 使用then()注册一个resolved状态的回调函数,并返回一个过滤后的promise  
    4. // 返回的filtered已经不是原来的Deferred或者Promise对象了  
    5. var filtered = deferred.then(function( value ) {  
    6.                 alert("trigger Deferred filter.value="+value);//5  
    7.                 return value * 2;  
    8.             });  
    9.   
    10. // 用过滤后的Promise再次注册回调函数           
    11. filtered.done(function( value ) {  
    12.     alert("filtered value=" + value);//10  
    13. });  
    14.    
    15. deferred.resolve( 5 );  

    我们用deferred.then()注册了一个完成状态下的回调函数,这个回调函数得到的值是5;之后用filtered这个新的Promise注册回调函数,这个回调函数中得到的值是10(第一个回调函数的返回结果)。现在我们看下JQuery官方对then的解释:

    These filter functions can return a new value to be passed along to the promise's .done() or .fail() callbacks, or they can return another observable object (Deferred, Promise, etc) which will pass its resolved / rejected status and values to the promise's callbacks. If the filter function used is null, or not specified, the promise will be resolved or rejected with the same values as the original.

    我们知道deferred.resolve()、deferred.reject()、deferred.notify()可以指定参数值,这个参数会传递给相应状态下的回调函数。如果我们使用的是done()、fail()、progress()注册的回调函数,那么某个状态下的所有回调函数得到的都是相同参数。但是如果我们使用了then()注册回调函数,那么第一回调函数的返回值将作为第二个回调函数的参数,同样的第二个函数的返回值是第三个回调函数的参数。可以对比下面的2段代码,体会下done()和then的差别。

    [javascript] view plain copy
     
    1. var deferred = $.Deferred();  
    2.   
    3. // done()返回的仍然是原来的Deferred对象  
    4. var done_ret = deferred.done(function(data){  
    5.     alert("data="+data);//5  
    6.     return 2 * data;  
    7. });  
    8. alert(deferred == done_ret);//true  
    9.   
    10. done_ret.done(function(data){  
    11.     alert("data="+data);//5  
    12. });  
    13.   
    14. deferred.resolve( 5 );  
    [javascript] view plain copy
     
    1. var deferred = $.Deferred();  
    2.   
    3. // then()返回的是一个新Promise对象  
    4. //then注册的回调函数的返回值将作为这个新Promise的参数  
    5. var then_ret = deferred.then(function(data){  
    6.     alert("data="+data);//5  
    7.     return 2 * data;  
    8. });  
    9. alert(then_ret == deferred);//false  
    10.   
    11. then_ret.done(function(data){  
    12.     alert("data="+data);//10  
    13. });  
    14.   
    15. deferred.resolve( 5 );  


    同样地,Deferred.then也能够实现rejected和pending状态的回调函数过滤。

    [javascript] view plain copy
     
    1. var defer = $.Deferred();  
    2. var filtered = defer.then( null, function( value ) {  
    3.     return value * 3;  
    4.   });  
    5.    
    6. defer.reject( 6 );  
    7.   
    8. filtered.fail(function( value ) {  
    9.   alert( "Value is ( 3*6 = ) 18: " + value );  
    10. });  

    下面这段代码可以实现chain tasks,解决异步操作中回调难的问题。

    [javascript] view plain copy
     
    1. var defered = $.Deferred();  
    2.   
    3. var promise1 = defered.then(function(data){  
    4.     alert(data);//  
    5.     return data+="1";  
    6. });  
    7.   
    8. var promise2 = promise1.then(function(data){  
    9.     alert(data);//1  
    10.     return data+="2";  
    11. });  
    12.   
    13. var promise3 = promise2.then(function(data){  
    14.     alert(data);//12  
    15.     return data+="3";  
    16. });  
    17.   
    18. promise3.done(function(data){  
    19.     alert(data);//123  
    20. });  
    21.   
    22. defered.resolve("");  

    正是由于then()这个特性,我们就可以上面复杂的AJAX嵌套改成如下形式:

    [javascript] view plain copy
     
      1. var promise1 = $.ajax(url1);  
      2. var promise2 = promise1.then(function(data){  
      3.     return $.ajax(url2, { "data": data });  
      4. });  
      5. var promise3 = promise2.then(function(data){  
      6.     return $.ajax(url3, { "data": data });  
      7. });  
      8. promise3.done(function(data){  
      9.     // data retrieved from url3  
      10. });  
  • 相关阅读:
    哈工大中文篇章关系语料
    MongoDB学习笔记~关于官方驱动集成IQueryable之后的一些事
    MongoDB学习笔记~为IMongoRepository接口更新指定字段
    MongoDB学习笔记系列
    MongoDB学习笔记~为IMongoRepository接口添加了增删改方法,针对官方驱动
    MongoDB学习笔记~为IMongoRepository接口添加了排序和表达式树,针对官方驱动
    Android NDK入门实例 计算斐波那契数列二生成.so库文件
    Spring Autowire自动装配
    在gem5的full system下运行 alpha编译的测试程序 running gem5 on ubuntu in full system mode in alpha
    工厂三兄弟之抽象工厂模式(二)
  • 原文地址:https://www.cnblogs.com/beimingbingpo/p/8547585.html
Copyright © 2011-2022 走看看