装饰异步函数的正确方法

Proper way to decorate async function

我想制作一个函数装饰器并测量异步函数的执行时间,并且 return 解析或拒绝缩进的结果而不进行装饰。任何线索如何实现这一目标?大多数指南都是关于同步功能的,不涉及异步世界。

这是说明所需功能的示例

async exampleFunction () {
try{
  const response = await aPromise() // The goals is to measure this one with a decorator measure(aPromise) and dispatch actions if the fetching takes a long time
}
catch (err){
  // Do something with error
}

像这样应该可以解决问题:

export function MeasureExecutionTime(target, propertyKey, descriptor)  {
  const fun = descriptor.value;
  descriptor.value = async function(...args) {
    const start = performance.now();
    const result = await fun.apply(target, args);
    const end = performance.now();
    console.log(`Execution time: ${end - start}`);
    return result;
  }
}

这是一个高阶函数,可以测量返回的承诺通过履行或拒绝来解决所花费的时间:

function measure(fn) {
  return async (...args) => {
    const begin = performance.now();
    try {
      return await fn(...args);
    } finally {
      const end = performance.now();
      console.log(`Execution time: ${end - begin}`);
    }
  };
}

用法示例:

exampleFunction();

async function exampleFunction() {
  try {
    const value = await measure(defer)('foo', 1000);
    // where normally you'd write:
    // const value = await defer('foo', 1000);
    console.log(`Resolved with ${value}`);
  } catch (reason) {
    console.log(`Rejected with ${reason}`);
  }
}

function measure(fn) {
  return async (...args) => {
    const begin = performance.now();
    try {
      return await fn(...args);
    } finally {
      const end = performance.now();
      console.log(`Execution time: ${end - begin}`);
    }
  };
}

function defer(result, ms) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const settle = Math.random() < 0.5 ? resolve : reject;
      settle(result);
    }, ms);
  });
}