No TypeScript é possível criarmos funções que alteram o comportamento de outras funções (ou classes), sem que tenhamos que alterar a implementação original da mesma. Essas funções são chamadas decorators
Um decorator pode ser declarado da seguinte maneira:
export default function decoratorFunction(logInSeconds: boolean = false) {
return function (
target: any, // contexto onde o decorator está inserido
propertyKey: string, // Nome do método
descriptor: PropertyDescriptor // description.value é o método original
) {
const originalFunction = descriptor.value;
// aqui podemos sobrescrever o comportamento do método original
descriptor.value = function (...args: any[]) {
const result = originalFunction.apply(this, args);
/*
aqui devolvemos o mesmo retorno do método original
à partir da chamada do decorator
*/
return result;
};
return descriptor; // é necessário retornar o próprio descriptor ao final
};
}
export default function logProcessingTime(logInSeconds: boolean = false) {
return function (
target: any,
propertyKey: string,
descriptor: PropertyDescriptor
) {
const originalFunction = descriptor.value;
descriptor.value = function (...args: any[]) {
let divisor = logInSeconds ? 1000 : 1;
let unidade = logInSeconds ? "seconds" : "milliseconds";
console.log("-----------------------");
console.log(`${propertyKey} function params: ${JSON.stringify(args)}`);
const initialTime = performance.now();
const result = originalFunction.apply(this, args);
console.log(`${JSON.stringify(result)} function result:`);
const finalTime = performance.now();
console.log(
`${propertyKey} took ${(finalTime - initialTime) / divisor} ${unidade} to be processed`
);
console.log("-----------------------");
return result;
};
return descriptor;
};
}
Agora basta importar o decorator em qualquer módulo do node que quisermos, e decorar nossa função com ele. Isso fará com que o tempo de execução da função seja mostrado no console do navegador.
Ex:
import logProcessingTime from './decorators/logProcessingTime';
@logProcessingTime()
async function listarUsuariosAsync() {
// Exemplo de chamada muito demorada à nossa API Rest
return API.get('/users');
}
// ........
const users = await listarUsuariosAsync(); // adiciona took 1.580000011017546ms to be processed