tapable 原理解析 2

tapable 原理解析 2

本文查看tapable中 sync 方式的方法運(yùn)行的方式以及context和intercept的運(yùn)行邏輯

1. SyncHook

執(zhí)行下面的代碼

const { SyncHook } = require('../lib/index')

const hook = new SyncHook(["arg1", "arg2"]);

hook.tap('1', function (arg1, arg2) {
  console.log('1', arg1, arg2)
})
hook.tap('2', function (arg1, arg2) {
  console.log('2', arg1, arg2)
})
hook.tap('3', function (arg1, arg2) {
  console.log('3', arg1, arg2)
})
hook.call('a1', 'a2', 'a3')

得到的函數(shù)和輸出結(jié)果:

function anonymous(arg1, arg2) {
  "use strict";
  var _context;
  var _x = this._x; 
  var _fn0 = _x[0];
  _fn0(arg1, arg2);
  var _fn1 = _x[1];
  _fn1(arg1, arg2);
  var _fn2 = _x[2];
  _fn2(arg1, arg2);
}
/* 輸出

1 a1 a2
2 a1 a2
3 a1 a2
*/

可以看到SyncHook的調(diào)用很簡(jiǎn)單,順序同步執(zhí)行不關(guān)心結(jié)果。

2. SyncBailHook

執(zhí)行代碼

const hook = new SyncBailHook(["arg1", "arg2"]); 
// ...
// 與前面一樣

得到的函數(shù)和輸出結(jié)果:

function anonymous(arg1, arg2) {
  "use strict";
  var _context;
  var _x = this._x;
  var _fn0 = _x[0];
  var _result0 = _fn0(arg1, arg2);
  if (_result0 !== undefined) {
    return _result0;
    ;
  } else {
    var _fn1 = _x[1];
    var _result1 = _fn1(arg1, arg2);
    if (_result1 !== undefined) {
      return _result1;
      ;
    } else {
      var _fn2 = _x[2];
      var _result2 = _fn2(arg1, arg2);
      if (_result2 !== undefined) {
        return _result2;
        ;
      } else {
      }
    }
  }
}

可以看到SyncBailHook的調(diào)用也很簡(jiǎn)單,只要執(zhí)行過程中一個(gè)訂閱函數(shù)返回值不為undefined就會(huì)暫停后續(xù)訂閱的執(zhí)行

3. SyncWaterfallHook

const hook = new SyncWaterfallHook(["arg1", "arg2"]); 
// ...
// 與前面一樣

得到的函數(shù)和輸出結(jié)果:

function anonymous(arg1, arg2) {
  "use strict";
  var _context;
  var _x = this._x;
  var _fn0 = _x[0];
  var _result0 = _fn0(arg1, arg2);
  if (_result0 !== undefined) {
    arg1 = _result0;
  }
  var _fn1 = _x[1];
  var _result1 = _fn1(arg1, arg2);
  if (_result1 !== undefined) {
    arg1 = _result1;
  }
  var _fn2 = _x[2];
  var _result2 = _fn2(arg1, arg2);
  if (_result2 !== undefined) {
    arg1 = _result2;
  }
  return arg1;

}

可以看到SyncWaterfallHook的調(diào)用也很簡(jiǎn)單,執(zhí)行過程中會(huì)使用上一個(gè)訂閱的返回值。

4. SyncLoopHook

const hook = new SyncLoopHook(["arg1", "arg2"]); 
// ...
// 與前面一樣

得到的函數(shù)和輸出結(jié)果:

function anonymous(arg1, arg2) {
  "use strict";
  var _context;
  var _x = this._x;
  var _loop;
  do {
    _loop = false;
    var _fn0 = _x[0];
    var _result0 = _fn0(arg1, arg2);
    if (_result0 !== undefined) {
      _loop = true;
    } else {
      var _fn1 = _x[1];
      var _result1 = _fn1(arg1, arg2);
      if (_result1 !== undefined) {
        _loop = true;
      } else {
        var _fn2 = _x[2];
        var _result2 = _fn2(arg1, arg2);
        if (_result2 !== undefined) {
          _loop = true;
        } else {
          if (!_loop) {
          }
        }
      }
    }
  } while (_loop);

}

可以看到SyncLoopHook的調(diào)用也很簡(jiǎn)單,只要執(zhí)行過程中一個(gè)訂閱函數(shù)返回值不為undefined,函數(shù)就會(huì)重新從第一個(gè)訂閱函數(shù)再次按順序執(zhí)行

5. SyncHook 結(jié)合context

執(zhí)行代碼


const hook = new SyncLoopHook(["arg1", "arg2"]);


hook.tap('1', function (arg1, arg2) {
  console.log('1', arg1, arg2)
})

hook.tap('2', function (arg1, arg2) {
  console.log('2', arg1, arg2)
})

hook.tap('3', function (arg1, arg2) {
  console.log('3', arg1, arg2)
})
hook.intercept({
  call: (source, target, routesList) => {
    console.log("intercept call");
  },
  loop: (source, target, routesList) => {
    console.log("intercept loop");
  },
  tap: (source, target, routesList) => {
    console.log("intercept tap");
  },
  register: (tapInfo) => {
    console.log("intercept register");
    console.log(`${tapInfo.name} is doing its job`);
    return tapInfo; // may return a new tapInfo object
  }
})

hook.call('a1', 'a2', 'a3')

得到的函數(shù)和輸出結(jié)果:

function anonymous(arg1, arg2) {
  "use strict";
  var _context = {};
  var _x = this._x;
  var _fn0 = _x[0];
  _fn0(_context, arg1, arg2);
  var _fn1 = _x[1];
  _fn1(arg1, arg2);
  var _fn2 = _x[2];
  _fn2(_context, arg1, arg2);

}

/* 輸出

1 a1 a2
2 a1 a2
okk
3 a1 a2
*/

當(dāng)在訂閱時(shí)開啟context選項(xiàng),在調(diào)用過程中就會(huì)給調(diào)用方法第一個(gè)參數(shù)傳遞context對(duì)象??梢栽趫?zhí)行過程中在不同的訂閱函數(shù)中傳遞數(shù)據(jù)

6. SyncHook 結(jié)合intercept

intercept代碼執(zhí)行過程

// intercept方法
{
        this.interceptors.push (interceptor));
        if (interceptor.register) {
            for (let i = 0; i < this.taps.length; i++) {
                this.taps[i] = interceptor.register(this.taps[i]);
            }
        }
}
// 同時(shí)在tap時(shí)調(diào)用 interceptor.register,
{
        for (const interceptor of this.interceptors) {
            if (interceptor.register) {
                const newOptions = interceptor.register(options);
                if (newOptions !== undefined) {
                    options = newOptions;
                }
            }
        }
}

可以看出register方法使用來接收原來的對(duì)訂閱的函數(shù)進(jìn)行攔截處理。

執(zhí)行代碼


const { SyncHook } = require('../lib/index')


const hook = new SyncHook(["arg1", "arg2"]);

hook.tap('1', function (arg1, arg2) {
  console.log('1', arg1, arg2)
})

hook.tap('2', function (arg1, arg2) {
  console.log('2', arg1, arg2)
})

hook.tap('3', function (arg1, arg2) {
  console.log('3', arg1, arg2)
})
hook.intercept({
  call: (source, target, routesList) => {
    console.log("intercept call");
  },
  tap: (source, target, routesList) => {
    console.log("intercept tap");
  },
  register: (tapInfo) => {
    console.log("intercept register");
    console.log(`${tapInfo.name} is doing its job`);
    return tapInfo; // may return a new tapInfo object
  }
})

hook.call('a1', 'a2', 'a3')

得到的函數(shù)和輸出結(jié)果:


function anonymous(arg1, arg2) {
  "use strict";
  var _context;
  var _x = this._x;
  var _taps = this.taps;
  var _interceptors = this.interceptors;
  _interceptors[0].call(arg1, arg2);
  var _loop;
  do {
    _loop = false;
    _interceptors[0].loop(arg1, arg2);
    var _tap0 = _taps[0];
    _interceptors[0].tap(_tap0);
    var _fn0 = _x[0];
    var _result0 = _fn0(arg1, arg2);
    if (_result0 !== undefined) {
      _loop = true;
    } else {
      var _tap1 = _taps[1];
      _interceptors[0].tap(_tap1);
      var _fn1 = _x[1];
      var _result1 = _fn1(arg1, arg2);
      if (_result1 !== undefined) {
        _loop = true;
      } else {
        var _tap2 = _taps[2];
        _interceptors[0].tap(_tap2);
        var _fn2 = _x[2];
        var _result2 = _fn2(arg1, arg2);
        if (_result2 !== undefined) {
          _loop = true;
        } else {
          if (!_loop) {
          }
        }
      }
    }
  } while (_loop);

}
/* 輸出: 
intercept register
1 is doing its job
intercept register
2 is doing its job
intercept register
3 is doing its job
current fn content: 

intercept call
intercept loop
intercept tap
1 a1 a2
intercept tap
2 a1 a2
intercept tap
3 a1 a2
*/

調(diào)用hook interceptor 方法,根據(jù)傳入配置的不同會(huì)再特定的時(shí)候?qū)?shù)或者執(zhí)行時(shí)進(jìn)行攔截。
上述打印的函數(shù)中展示了在發(fā)布時(shí),對(duì)于interceptor中的call,loop和tap鉤子的調(diào)用過程;
loop方法只在有循環(huán)的條件時(shí)調(diào)用。
剩下的register方法是在訂閱時(shí)攔截訂閱函數(shù)的參數(shù),處理后返回參數(shù)。

    intercept(interceptor) {
        this._resetCompilation();
        this.interceptors.push(Object.assign({}, interceptor));
        if (interceptor.register) {
            for (let i = 0; i < this.taps.length; i++) {
                this.taps[i] = interceptor.register(this.taps[i]);
            }
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容