Ruby's Louvre

每天学习一点点算法

导航

解读JSDeferred源码2

继续第一部分最后的例子:

        Deferred.define();
        //同步处理
        next(function func1(){
          alert("a1")
        })
        .next(function func2(){
          alert("a2")
        })
        //异步处理
        next(function func1(){
          alert("b1")
        })
        .wait(0)   // ←注意这里
        .next(function func2(){
         alert("b2")
        })
        //依次alerts b1 a1 a2 b2
    

第一部分就提到,如果光是调用next,只有第一个next是异步,其他是同步执行。而多了一个wait就不一样了, 看到没有,完全打乱了执行顺序。首先我们先找到wait函数吧。

我们是其原型链中是找不到wait函数的,但找到一个同名的静态方法:

      Deferred.register = function (name, fun) {
        this.prototype[name] = function () {
          return this.next(Deferred.wrap(fun).apply(null, arguments));
        };
      };

      Deferred.wrap = function (dfun) {
        return function () {  // ←この関数を便宜的に A と呼ぶことにするよ
          var a = arguments;
          return function () {
            return dfun.apply(null, a);
          };
        };
      };

      Deferred.register("loop", Deferred.loop);
      Deferred.register("wait", Deferred.wait);
    

Deferred.register的作用是把相关的静态方法变成实例方法。在最新的版本中,wrap已经整合到register中:

      Deferred.register = function (name, fun) {
        this.prototype[name] = function () {
          var a = arguments;
          return this.next(function () {
            return fun.apply(this, a);
          });
        };
      };
      Deferred.register("loop", Deferred.loop);
      Deferred.register("wait", Deferred.wait);
    

我们知道实例方法next会创建一个新实例,并修正其callback.ok。而这里相当于把其callback.ok设为function () {return fun.apply(this, a); }。 这是一个curry,需要补全参数,结合我们的例子,它将为0,而fun则实质为Deferred.wart。换言之,callback.ok的值实质为 function (n) {return eferred.wait(n); }。为方便起见,我们把这次创建的实例称之为,d_implicit,其对应回调函数为implicit。

好了,我们再回到_fire函数。

    _fire : function (okng, value) {
        var next = "ok";
        try {
            value = this.callback[okng].call(this, value);
        } catch (e) {
            next  = "ng";
            value = e;
            if (Deferred.onerror) Deferred.onerror(e);
        }
        if (value instanceof Deferred) {
            value._next = this._next;
        } else {
            if (this._next) this._next._fire(next, value);
        }
        return this;
    }
    

在try_catch中,我们执行implicit,从而调用Deferred.wait,而Deferred.wait会产生一个新的实例d_wait, 然后在value instanceof Deferred分支中将其_next设为d_implicit._next(d2)。然后等,等wait中的setTimeout函数执行。 setTimeout里面是一个实例函数call,调用者为d_wait。call会再次调用_fire,并且由于d_wait的回调函数为function(s){return x} 因此,会再次调用_fire,让其_next执行其callback。

整个构思实在惊为天人啊!

      next(function func1(){
        //创建一个Deferred实例d1,
        //callback.ok = func1,_next = d_implicit(见下★)
        alert("b1")
      })
      .wait(0)
      //next->post 创建一个 Deferred实例d_implicit ★
      //callback.ok = function implicit(a) {return fun.apply(this, a);  }
      //callback.ok = function implicit(a) {return Deferred.wait(a);  }
      //_next = d2(见下★★)
      .next(function func2(){
        //next->post 创建一个 Deferred实例d2 ★★
        //callback.ok = func2
        //_next = new Deferred
        alert("b2")
      })
      //上面是静态部分
      //下面动态部分,
      //d1调用func2,返回undefined,因此执行
      //d_implicit调用function implicit(a) {return Deferred.wait(a);  }
      //其间产生d_wait实例,callback_ok为function(x){return x},_next = new Deferred
      //但在_fire中的if(value instanceof Deferred)中,重置d_wait的_next为d_implicit.next,
      //即d_wait的_next为d2
      //wait中的setTimeout会执行d_wait.call(n),call再调用_fire
      //d_wait调用function (x) {return x;  },由于非Deferred实例,因此再次调用_fire
      //让其_next执行其callback,而_next即为d2
    
d1静态next创建
callbackfunc1
_nextd_implicit
d_implicit实例wait创建(wait->next->_post)
callbackfunction implicit(a) {return Deferred.wait(a); }
_nextd2
d2实例next创建(next->_post)
callbackfunc2
_nextnull
d_wait静态wait创建
callbackfunction(x){return x}
_nextd_implicit._next

执行过程为:

      //d1 setTimeout d_implicit d_wait setTimeout d2
    

posted on 2010-04-20 00:51  司徒正美  阅读(302)  评论(0编辑  收藏  举报