Как выполнить функцию до и после каждого вызова метода класса? - PullRequest
1 голос
/ 23 февраля 2020

Я хочу вставить в обработчики до и после выполнения функции в javascript классах.

Допустим, у меня есть такой класс.

class Foo {
  method1(p1, p2) {
    this.p1 = p1;
    this.p2 = p2;
  }

  method2(p3) {
    this.p3 = p3;
  }
}

Я хочу определить хук до и после для этих существующих методов класса. Примерно так.

class Foo {
  before(funName, ...params){
    // Should print ('method1', [p1, p2]) when method 1 is called
    // and ('method2', [p3]) when method 2 is called
    console.log(funName, params)
  }
  after(funName, result){
    // Should print the function name followed by its result
    console.log(funName, result)
  }
  method1(p1, p2) {
    this.p1 = p1;
    this.p2 = p2;
  }
  method2(p3) {
    this.p3 = p3;
  }
}

export default Foo;

Каков наилучший способ реализации этих ловушек с минимальными изменениями в существующем коде?

1 Ответ

1 голос
/ 24 февраля 2020

Вот примерное решение проблемы:

// we iterate over all method names
Object.getOwnPropertyNames(Foo.prototype).forEach((name) => {

  // First to do: we save the original method. Adding it to prototype
  // is a good idea, we keep 'method1' as '_method1' and so on
  Foo.prototype['_' + name] = Foo.prototype[name];

  // Next, we replace the original method with one that does the logging
  // before and after method execution. 
  Foo.prototype[name] = function() {

    // all arguments that the method receives are in the 'arguments' object
    console.log(`Method call: method1(${Object.values(arguments).join(', ')})`);

    // now we call the original method, _method1, on this with all arguments we received
    // this is probably the most confusing line of code here ;)
    // (I never user this['method'] before - but it works)
    const result = this['_' + name](...arguments);

    // here is the post-execution logging
    console.log(`Method result: ${result}`);

    // and we need to return the original result of the method
    return result;
  };
});

Обратите внимание, что этот код не является частью самого класса, выполните его как обычный скрипт.

И есть велика вероятность того, что это краткое доказательство концепции рушится на реальных классах и требует некоторых дополнительных проверок и специальных обработчиков, особенно для получения правильных результатов регистрации. Но с вами работает класс Foo.

Вот рабочий пример: https://codesandbox.io/s/great-fog-c803c

...