• 第三十四课:jQuery Deferred详解2


    上一课主要分析了jQuery1.51版本的jQuery Deferred。在jQuery1.6中,jQuery Deferred添加了两个方法,always,pipe。

    always用来添加回调,无论成功还是失败,都会执行。

    pipe就是管道的意思,对回调使用瀑布模型,上一个回调的返回值供下一个会调使用。

    我们举个例子来说明下pipe与then的区别:

    var deferred = $.Deferred();  //返回的是Deferred对象

    var promise = deferred.pipe(function(a){return a*2}).pipe(function(a){return a*4;})   //pipe方法的返回值是Promise对象,因此promise与deferred不相等。

    deferred.resolve(5);     //执行这个函数后,就会调用pipe添加进来的回调函数。第一个回调函数中的a=5,然后返回10给第二个回调函数,因此第二个回调中的a=10。

    $.Deferred().then(function(a){return a*2;}).then(function(a){return a*4;}).resolve(5);

    第一个回调函数中的a=5,第二个回调函数中的a=10,跟pipe方法一样。它们的区别是then方法返回的是Deferred对象,因而可以进行链式操作,而pipe方法返回的是Promise对象,不能进行链式操作。

    在这个版本的jQuery中,Deferred开始在jQuery内部大规模应用了,包括queue模块,Ajax模块。

    举个很好的例子:

    var stuff1 = function(deferred){

      setTimeout(function(){deferred.resolve()},1000);

    };

    var stuff2 = function(deferred){

      setTimeout(function(){deferred.resolve()},500);

    };

    var stuff3 = function(deferred){

      setTimeout(function(){deferred.resolve()},800);

    };

    var stuff4 = function(deferred){

      setTimeout(function(){deferred.resolve()},800);

    };

    $.when(    //此方法接受了三个Deferred对象,只有等这三个Deferred对象的状态结束后(也就是执行了各自的resolve方法后),才会执行then添加的回调方法。

      $.Deferred(stuff1),   //此方法会执行stuff1方法,并且把新创建的Deferred对象传进去,返回此Deferred对象,1秒后,调用此Deferred对象的resolve方法。

      $.Deferred(stuff2),   //同上,只是异步处理的时间不一样。

      $.Deferred(stuff3)    //同上,这里的setTimeout的异步处理,我们可以当做是ajax请求的时间长度。

    ).then(stuff4);   //给$.when()方法返回的Deferred对象添加回调函数stuff4。等when方法中传入的所有Deferred对象的状态结束后,就会执行此回调stuff4.

    这段代码的理解你可以当做是:有三个ajax请求,请求的地址不一样,我们需要等这三个ajax请求都返回后,把这三个请求回来的数据进行整合处理,才能进行最后一个ajax请求。

    jQuery1.7添加了Callbacks模块,具体可以看:http://www.cnblogs.com/chaojidan/p/4165818.html。

    而且也改写了Deferred模块。这个时候的Deferred,它是一个三链结构(doneList,failList,progressList)。progressList链添加了三个API,progress,notify,notifyWith,用来给此链添加回调和触发回调。progressList链是用来干嘛的?我们知道成功队列doneList与失败队列failList都是一次性的,也就是说触发了一次就不能再触发了。但是有时,我们需要反复触发,那么就可以用progressList来解决。

    举个例子:

    var a = $.Deferred();

    a.done(function(x){console.log(x);}).done(function(x){console.log(x)});

    a.resolve(1);

    如果大家看了上一课的jQuery Deferred的源码,就知道,创建了一个新的延迟对象a,然后通过done方法添加了两个成功回调函数,最后通过resolve方法触发a的成功回调,因此会执行这两个成功回调函数,打印出两个1.

    这时如果你再调用a.resolve(2);再次触发a的成功回调,不会打印出两个1.

    但是progressList可以,

    var b = $.Deferred();

    b.progress(function(x){console.log(x);}).progress(function(x){console.log(x)});

    b.notify(1);

    b.notify(2);

    第一个notify会打印出两个1,第二个notify会打印出两个2.

    从上面的例子中,大家可以看出,doneList,failList触发一次状态后,就会结束了,你后面再次触发同样的状态,是不会执行回调函数的。但是progressList可以触发多次状态,也就意味着你只要调用notify,就会执行progress添加的回调函数。

    jQuery1.8又对Deferred进行了重构,不过思路是一致的。

    Promise/A隶属于Promise规范,而Promise规范则又隶属于CommonJS。

    Promise/A规范大概是这样描述的:一个带有then方法的对象,它拥有3个状态,fulfilled,rejected,pending。then方法可以传入三个函数,一个是成功时执行的回调函数onFulfill,一个是失败时执行的回调函数onReject,一个是进行中执行的回调函数onNotify,它不会改变对象的状态(刚开始对象就处于pending,当执行成功回调函数onFulfill后,对象就会变成fulfilled状态,当执行失败回调函数onReject后,对象就会变成rejected状态,当执行进行中回调函数onNotify后,对象状态不会改变,还是pending状态)。这三个函数都是可选的,如果是非函数,就忽略掉。then方法会返回一个新的Promise对象,以便能够实现链式操作。

    后来人们在Promise/A的规范上添加了更多的细节,形成了Promise/A+规范。现在市面上有三大Promise/A+库,分别是:Q,RSVP,when。其中,Q的微缩版被整进angular.js,RSVP被整进了ember.js。这两个库就是著名的MVVM库。后面的章节将会讲到这两个库,我也很期待。

    js异步处理的前景

    未来的javascript将支持yield生成器(generator),目前只有Firefox浏览器有,但是需要自己打开实验性开关。

    <script type="text/javascript; version=1.7">    //这里改成1.8也行

      //这里面就可以使用yield了

    </script>

    此yield,可以让我们轻松的以同步的形式写出异步的代码。你只需要将它们放到某个函数体内。相应的库有:taskjs,gens,tamejs等。

    有人对各种不同实现的异步库进行性能评测,基于原生生成器的库总体上占优势。yield语句比回调更能及时的工作,耗时更少。

    但是在目前,实现生成器的代码量非常大,而实现Promise则相对轻松一些,因此Promise是当下最廉价的异步方案。

    yield还没有真正的发展起来,因此不用精读。知道有这么一个东西就行。

     下一课,将讲解Ajax,大家可以先去看一下Ajax Hacks这本书。

    加油!

  • 相关阅读:
    JavaScript入门知识点整理
    正则表达式
    bootstrap css编码规范
    JavaScript高级编程(学习笔记)
    【 D3.js 选择集与数据详解 — 2 】 使用data()绑定数据
    bootstrap table:JQuery中each方法绑定blur事件监听input输入是否合法,进入死循环
    bootstrap-table中导出excel插件bootstrap-table-export使用
    托业考后感
    《Pride and Prejudice》英文版读后记忆
    迷茫的当下,我在做什么
  • 原文地址:https://www.cnblogs.com/chaojidan/p/4195102.html
Copyright © 2020-2023  润新知