解读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创建 | |
callback | func1 | |
_next | d_implicit | |
d_implicit | 实例wait创建(wait->next->_post) | |
callback | function implicit(a) {return Deferred.wait(a); } | |
_next | d2 | |
d2 | 实例next创建(next->_post) | |
callback | func2 | |
_next | null | |
d_wait | 静态wait创建 | |
callback | function(x){return x} | |
_next | d_implicit._next |
执行过程为:
//d1 setTimeout d_implicit d_wait setTimeout d2