首页 > 解决方案 > 如何测量多次调用异步函数的时间

问题描述

我在理解 js 中的异步函数如何工作时遇到了问题。所以我需要调用异步函数 5 次并测量每次执行的持续时间。最后我应该有一个包含 5 个时间值的数组。我有这样的

for (let i = 0; i < 5; i++) {
    const run = async () => {
    await test(thisTest, filename, unitTestDict);
    };
    measure(run).then(report => {
                        // inspect
                        const {tSyncOnly, tSyncAsync} = report;
                        // array.push(tSyncAsync) 
                        console.log(`∑ = ${tSyncAsync}ms \t`);
                    }).catch(e => {
                        console.error(e)
                    });
}

在这里 我找到了时间测量功能的实现:


class Stack {
    constructor() {
        this._array = []
    }

    push(x) {
        return this._array.push(x)
    }

    peek() {
        return this._array[this._array.length - 1]
    }

    pop() {
        return this._array.pop()
    }

    get is_not_empty() {
        return this._array.length > 0
    }
}

class Timer {
    constructor() {
        this._records = new Map
        /* of {start:number, end:number} */
    }

    starts(scope) {
        const detail =
            this._records.set(scope, {
                start: this.timestamp(),
                end: -1,
            })
    }

    ends(scope) {
        this._records.get(scope).end = this.timestamp()
    }

    timestamp() {
        return performance.now()
    }

    timediff(t0, t1) {
        return Math.abs(t0 - t1)
    }

    report(scopes, detail) {
        let tSyncOnly = 0;
        let tSyncAsync = 0;
        for (const [scope, {start, end}] of this._records)
            if (scopes.has(scope))
                if (~end) {
                    tSyncOnly += end - start;
                    tSyncAsync += end - start;
                    const {type, offset} = detail.get(scope);
                    if (type === "Timeout")
                        tSyncAsync += offset;
                }
        return {tSyncOnly, tSyncAsync}
    }
}

async function measure(asyncFn) {
    const stack = new Stack;
    const scopes = new Set;
    const timer = new Timer;
    const detail = new Map;
    const hook = createHook({
        init(scope, type, parent, resource) {
            if (type === 'TIMERWRAP') return;
            scopes.add(scope);
            detail.set(scope, {
                type: type,
                offset: type === 'Timeout' ? resource._idleTimeout : 0
            })
        },
        before(scope) {
            if (stack.is_not_empty) timer.ends(stack.peek());
            stack.push(scope);
            timer.starts(scope)
        },
        after() {
            timer.ends(stack.pop())
        }
    });
    return await new Promise(r => {
        hook.enable();
        setTimeout(() => {
            asyncFn()
                .then(() => hook.disable())
                .then(() => r(timer.report(scopes, detail)))
                .catch(console.error)
        }, 1)
    })
}

我可以在循环中调用它,并在每次迭代时获取 console.log:

measure(run).then(report => {
                        // inspect
                        const {tSyncOnly, tSyncAsync} = report;
                        // array.push(tSyncAsync) 
                        console.log(`∑ = ${tSyncAsync}ms \t`);
                    }).catch(e => {
                        console.error(e)
                    });

但是当我尝试将此控制台值推送到数组时,什么也没有出现,数组仍然是空的。有没有办法填写?

标签: javascriptnode.jsasynchronoustime

解决方案


推荐阅读