preface

All hooks provide additional interceptor apis.

This article looks at the use of interceptors.

Interception interceptor

call

Type: (… args) => void

This method is executed before the defined Hook is called. That is, before the Call, callAsync, and Promise methods.

tap

Type: (tap: tap) => void

This method is executed before the subscription function is executed.

loop

Type: (… args) => void

This method is executed before the subscription function of a Hook with loop capability is executed.

register

Type: (tap, tap) = > tap | is undefined

This method is executed before each subscription function and can be used to modify the Tap object of the subscription function.

This to be analyzed source code, can clearly understand its function.

The sample

The sample code

Take a look at the interceptor functionality with an example:

const {
  AsyncSeriesLoopHook
} = require('tapable');

const hook = new AsyncSeriesLoopHook(['name'.'age']);
let count1 = 0;
let count2 = 0;

hook.intercept({
  call: () = > {
    console.log('call');
  },
  tap: tapInfo= > {
    console.log('tap', tapInfo);
  },
  register: tapInfo= > {
    console.log('register', tapInfo);
    return tapInfo;
  },
  loop: () = > {
    console.log('intercept loop'); }}); hook.tapAsync('js'.(name, age, callback) = > {
  if (++count1 >= 2) {
    console.log('js', name, age, count1);
    callback();
  } else {
    console.log('js', name, age, count1);
    callback(null.'js1'); }}); hook.tapAsync('node'.(name, age, callback) = > {
  if (++count2 >= 2) {
    console.log('node', name, age, count2);
    callback();
  } else {
    console.log('node', name, age, count2);
    callback(null.'node2'); }}); hook.callAsync('naonao'.2.err= > {
  console.log('end', err);
});
Copy the code

Print the result

register { type: 'async'.fn: [Function (anonymous)], name: 'js' }
register { type: 'async'.fn: [Function (anonymous)], name: 'node' }
call
intercept loop
tap { type: 'async'.fn: [Function (anonymous)], name: 'js' }
js naonao 2 1
intercept loop
tap { type: 'async'.fn: [Function (anonymous)], name: 'js' }
js naonao 2 2
tap { type: 'async'.fn: [Function (anonymous)], name: 'node' }
node naonao 2 1
intercept loop
tap { type: 'async'.fn: [Function (anonymous)], name: 'js' }
js naonao 2 3
tap { type: 'async'.fn: [Function (anonymous)], name: 'node' }
node naonao 2 2
end undefined
Copy the code

Print the hooks. CallAsync

Print the hook. CallAsync method at this point:

function anonymous(name, age, _callback) {
  "use strict";
  var _context;
  var _x = this._x;
  var _taps = this.taps;
  var _interceptors = this.interceptors;
  _interceptors[0].call(name, age);
  var _looper = (function () {
    var _loopAsync = false;
    var _loop;
    do {
      _loop = false;
      _interceptors[0].loop(name, age);
      function _next0() {
        var _tap1 = _taps[1];
        _interceptors[0].tap(_tap1);
        var _fn1 = _x[1];
        _fn1(name, age, (function (_err1, _result1) {
          if (_err1) {
            _callback(_err1);
          } else {
            if(_result1 ! = =undefined) {
              _loop = true;
              if (_loopAsync) _looper();
            } else {
              if(! _loop) { _callback(); }}}})); }var _tap0 = _taps[0];
      _interceptors[0].tap(_tap0);
      var _fn0 = _x[0];
      _fn0(name, age, (function (_err0, _result0) {
        if (_err0) {
          _callback(_err0);
        } else {
          if(_result0 ! = =undefined) {
            _loop = true;
            if (_loopAsync) _looper();
          } else{ _next0(); }}})); }while (_loop);
    _loopAsync = true;
  });
  _looper();

}
Copy the code

We will ignore register and see how it is executed in the next source code analysis.

As you can see from the code:

  • The interceptor’s call (_interceptors[0].call in the code) is executed first and only once, receiving the same arguments that were passed in the Hook call
  • The interceptor’s loop (_interceptors[0].loop in this code) is executed on each loop and receives arguments that were passed in the Hook call
  • The interceptor tap (_interceptors[0].tap in this code), which is executed before each subscription function is executed, receives a TAP object as an argument.

The Context object

Plug-ins and interceptors can optionally access an optional Context object, which can be used to pass arbitrary values to subsequent plug-ins and interceptors.

The sample

The sample code

const {
  AsyncSeriesLoopHook
} = require('tapable');

const hook = new AsyncSeriesLoopHook(['name'.'age']);

hook.intercept({
  context: true.tap: (context, tapInfo) = > {
    console.log('tap', tapInfo);
    if (context) {
      context.show = true; }}}); hook.tapAsync('js'.(name, age, callback) = > {
  console.log('js', name, age);
  callback();
});

hook.tapAsync({
  context: true.name: 'css'
}, (context, name, age, callback) = > {
  if (context && context.show) {
    console.log('css context', name, age);
    callback();
  } else {
    console.log('css', name, age); callback(); }}); hook.tapAsync('node'.(name, age, callback) = > {
  console.log('node', name, age);
  callback();
});

hook.callAsync('naonao'.2.err= > {
  console.log('end', err);
});
Copy the code

Print the result

tap { type: 'async'.fn: [Function (anonymous)], name: 'js' }
js naonao 2
tap {
  type: 'async'.fn: [Function (anonymous)],
  context: true.name: 'css'
}
css context naonao 2
tap { type: 'async'.fn: [Function (anonymous)], name: 'node' }
node naonao 2
end undefined
Copy the code

The second subscription function uses context. It gets the context.show property, so it prints CSS Context naonao 2.

So we can pass some values down through the context.

However, in the latest version of Tapable, the DeprecationWarning: Hook. Context is deprecated and will be removed. So later versions will remove the context.

Print the hooks. TapAsync

Print the hook. TapAsync method at this point:

function anonymous(name, age, _callback) {
  "use strict";
  var _context = {};
  var _x = this._x;
  var _taps = this.taps;
  var _interceptors = this.interceptors;
  var _looper = (function () {
    var _loopAsync = false;
    var _loop;
    do {
      _loop = false;
      function _next1() {
        var _tap2 = _taps[2];
        _interceptors[0].tap(_context, _tap2);
        var _fn2 = _x[2];
        _fn2(name, age, (function (_err2, _result2) {
          if (_err2) {
            _callback(_err2);
          } else {
            if(_result2 ! = =undefined) {
              _loop = true;
              if (_loopAsync) _looper();
            } else {
              if(! _loop) { _callback(); }}}})); }function _next0() {
        var _tap1 = _taps[1];
        _interceptors[0].tap(_context, _tap1);
        var _fn1 = _x[1];
        _fn1(_context, name, age, (function (_err1, _result1) {
          if (_err1) {
            _callback(_err1);
          } else {
            if(_result1 ! = =undefined) {
              _loop = true;
              if (_loopAsync) _looper();
            } else{ _next1(); }}})); }var _tap0 = _taps[0];
      _interceptors[0].tap(_context, _tap0);
      var _fn0 = _x[0];
      _fn0(name, age, (function (_err0, _result0) {
        if (_err0) {
          _callback(_err0);
        } else {
          if(_result0 ! = =undefined) {
            _loop = true;
            if (_loopAsync) _looper();
          } else{ _next0(); }}})); }while (_loop);
    _loopAsync = true;
  });
  _looper();

}
Copy the code

As you can see from the code, var _context = {} is defined and passed as the first argument when the interceptor executes the tap method.

For subscription functions, if context: true is set, _context is passed as the first argument when called; Otherwise, it’s not passed on.

conclusion

This article covers interceptors and Context objects.

In the next post, we will start with the source code and uncover Tapable.

More exciting, please pay attention to the wechat public number: make a noise front end