es6裝飾器異步使用

裝飾器簡介

個人理解,某些場景需要在不改變原有類和屬性的基礎上擴展一些功能,所以裝飾器就出現了。

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

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

使用場景

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

常用例子

一般用這個日誌模塊來舉例,不過它是同步的

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 () {
    console.log(`Calling "${name}" with`, arguments);
    let args = arguments;
    return new Promise((resolve) => {
      setTimeout(function () {
        // args = [...args, 100];
        init = 100;
        resolve(oldValue.apply(null, args));
      }, 100);
    });
  };
  return descriptor;
}

const math = new Maths();

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章