es6裝飾器異步使用

裝飾器簡介

我的理解,某些場景須要在不改變原有類和屬性的基礎上擴展一些功能,因此裝飾器就出現了。java

裝飾器的寫法是在類或類屬性以前,加個方法名。學過java的同窗應該比較熟悉這種寫法,Spring中鋪天蓋地都是註解。具體細節處處都是,就不贅述了。node

不過截止到今天(2019年8月),遺憾的是nodejs還未原生支持,仍然須要babel編譯。api

使用場景

忽然想到用裝飾器,固然是有業務須要。寫了一個api類,全部暴露的函數都須要進行一步初始化操做。但初始化代碼又不歸我控制,且是異步接口請求,不能當即執行,這就致使每一個函數都要調用一遍這個init方法。由於加了緩存,每一個都要判斷有沒有緩存,比較噁心。緩存

經常使用例子

通常用這個日誌模塊來舉例,不過它是同步的babel

class Math {
  @log
  add(a, b) {
    return a + b;
  }
}

function log(target, name, descriptor) {
  var oldValue = descriptor.value;

  descriptor.value = function() {
    console.log(`Calling "${name}" with`, arguments);
    return oldValue.apply(null, arguments);
  };

  return descriptor;
}

const math = new Math();

// passed parameters should get logged now
math.add(2, 4);

修改成異步

let init = 0;
class Maths {
  @log
  add (a, b) {
    return a + b + init;
  }
}

function log (target, name, descriptor) {
  let oldValue = descriptor.value;
  descriptor.value = function (...args) { //有時候,arguments指向不對,多是babel的鍋?
    console.log(`Calling "${name}" with`, args);
    return new Promise((resolve) => {
      setTimeout(function () {
        // args = [...args, 100];
        init = 100;
        resolve(oldValue.apply(target, args)); //this指向
      }, 100);
    });
  };
  return descriptor;
}

const math = new Maths();

(async () => {
  let a = await math.add(2, 4);
  console.log(a);
})();

在具體函數前加了裝飾器後,會先執行log方法,這樣緩存的變量就修改了。雖然結果變成異步的,但也知足個人須要了。app

相關文章
相關標籤/搜索