1

I want to write a function to measure the performance of parts of code (other methods) that could return a value. This is what I came out at the moment:

const fn = async (): Promise<any> => {
    setTimeout(async (): Promise<any> => {
        return new Promise((resolve) => resolve('Hello World!'));
    }, 3000);
};

async measure(fn: () => Promise<any>): Promise<any> {
    const startTime = this.performance.now();
    const result = await functionToMeasure();
    const endTime = this.performance.now();

    const executionTime = endTime - startTime;
    console.log(`Executed in ${executionTime} ms`);

    return result;
}

const result = async measure(functionToMeasure); // result is undefined

The result is that functionToMeasure actually runs but it never returns something and at the moment I can use it only with void function.

I'd like to fix it if possible, or I can change completely if there's a better way to do it.

EDIT:

Actual code

const callback = async (): Promise<any> => {
    return await doSomethingAndReturn();
};
const searchResults: string[] = await measure(callback);

Do I've to wrap doSomethingAndReturn in an async Promise?

chenny
  • 385
  • 2
  • 10
  • 32
  • You should be wrapping the setTimeout in the Promise's executor function. At the moment you are wrapping the Promise inside of the setTimeout callback. See [What is the JavaScript version of sleep()?](https://stackoverflow.com/q/951021) – Nick Parsons Dec 13 '20 at 11:36

1 Answers1

1

You need to wrap the setTimeout call in a promise and then resolve the result, so it should look something like this:

const {performance} = require('perf_hooks');

async function executeAndMeasure(fn) {
    const startTime = performance.now();
    const result = await fn();
    const endTime = performance.now();

    const executionTime = endTime - startTime;
    console.log(`Executed in ${executionTime} ms`);

    return result;
}

function someFnThatReturnsAPromise() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve("Hello World");
        }, 3000);
    })
}

async function someAsyncFunction() {
    return 123;
}

(async () => {
    let result = await executeAndMeasure(someFnThatReturnsAPromise);
    console.log(`result was ${result}`);
    result = await executeAndMeasure(someAsyncFunction);
    console.log(`result was ${result}`);
})();
eol
  • 15,597
  • 4
  • 25
  • 43
  • It works! But just one more question: that code actually comes from my unit tests. So to call another `async` function, do I've to wrap it in a promise? – chenny Dec 13 '20 at 11:49
  • It it's already `async`, no. Defining a method `async` automatically returns the return value in a promise. See my edit. – eol Dec 13 '20 at 11:50
  • I undestand. Is it easy to enable the `measure` function to call also callbacks with parameters? – chenny Dec 13 '20 at 12:12
  • Nowadays I'd always try to avoid callbacks as `async/await` allows for much cleaner code. If you really want to do it, you'd have to do the calculation for the `executionTime` in the callback. – eol Dec 13 '20 at 12:17