ES7之Decorators實現AOP示例


在上篇博文CoffeeScript實現Python裝潢器中,筆者利用CoffeeScript支持的高階函數,以及方法調用可省略括符的特性,實現了一個類似Python裝潢器的日志Demo。這只是一種偽實現,JavaScript實現裝潢器,我們需要等到ECMAScript7才行,在ES7特性中帶來了Decorators,它就是我們所需要的裝潢器特性。雖然它是ES7的特性,但在Babel大勢流行的今天,我們可以利用Babel來使用它。關於Babel的推薦文章,請參見另一篇文章Babel-現在開始使用 ES6

下面我們仍然和上節CoffeeScript實現Python裝潢器一樣,實現一個ES7 Decorators版的日志攔截示例。我們希望得到的代碼效果如下:

class MyClass {
  @log('MyClass add')
  add(a, b){
    return a + b;
  }
  @log('MyClass product')
  product(a, b){
    return a * b;
  }
  @log('MyClass error')
  error(){
     throw 'Something is wrong!';
   }
}

在ES7中Decorators,也是一個函數,我們只需要在它前面加上@符號,並將它標注在特定的目標,如class、method等,則可以實現方法的包裹攔截。它的傳入參數有:target, name, descriptor。它們分別標記目標,標記目標名稱,以及目標描述信息。在descriptor中,包括configurable、enumerable、writable,value四個屬性。它們分別可以控制目標的讀寫、枚舉,以及目標值。

所以我們可以如下實現:

let log = (type) => {
    const logger = new Logger('#console');
    return (target, name, descriptor) => {
      const method = descriptor.value;
      descriptor.value =  (...args) => {
            logger.info(`(${type}) before function execute: ${name}(${args}) = ?`);
            let ret;
            try {
                ret = method.apply(target, args);
                logger.info(`(${type})after function execute success: ${name}(${args}) => ${ret}`);
            } catch (error) {
                logger.error(`(${type}) function execute error: ${name}(${args}) => ${error}`);
            } finally {
                logger.info(`(${type}) function execute done: ${name}(${args}) => ${ret}`);
            }
            return ret;
        }
    }
}

首先我們將原來的方法體緩存起來,直到方法調用時,才會被調用以實現方法調用前后的日志攔截,打印相關信息。示例的效果如下:

es7 decorators log aop

整個demo示例,你也可以在codepen上細細把玩:

See the Pen ES7 Decorators by green (@greengerong) on CodePen.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM