JavaScript中使用await兼容同步/异步函数时性能极差的问题
优化混合同步/异步函数场景下的await性能瓶颈
我完全懂你这个头疼的问题——当类库要兼容同步和异步函数,统一用await处理时,哪怕是纯同步函数也会被强制套上Promise的壳,这种额外开销在高频调用场景下会被放大得特别明显,直接导致性能暴跌。
问题根源
await的机制是:不管右侧表达式是不是Promise,都会把它包装成一个已决议的Promise,然后将后续逻辑放到微任务队列中执行。哪怕是像a()这种直接返回字符串的同步函数,await也会走一遍完整的Promise调度流程——创建Promise实例、加入微任务队列、等待当前调用栈清空后再执行后续代码。单次调用的开销看似微小,但大量累积后,性能差距就会变得极端明显。
解决方案:分情况处理同步/异步逻辑
最稳妥且通用的方式是先执行函数,再判断返回值是否为Promise,仅当返回值是Promise时才使用await,这样同步函数就能完全避开Promise的额外开销:
function syncFn() { return 'sync result'; } async function asyncFn() { return 'async result'; } function syncReturnPromise() { return Promise.resolve('promise from sync'); } async function handleFunction(fn) { const result = fn(); // 仅当返回值是Promise时才await if (result instanceof Promise) { await result; } // 同步返回值或await后的结果都可以直接使用 console.log(result); } handleFunction(syncFn); // 直接调用,无Promise开销 handleFunction(asyncFn); // 正常等待异步结果 handleFunction(syncReturnPromise); // 正确处理返回Promise的同步函数
如果你的场景能确保函数要么是async函数,要么是纯同步函数(不会手动返回Promise),也可以直接判断函数类型:
async function handleFunction(fn) { if (fn.constructor.name === 'AsyncFunction') { await fn(); } else { fn(); } }
不过这种方式有局限性:如果存在普通函数手动返回Promise的情况,会被误判为同步函数,导致无法等待结果,因此更推荐第一种判断返回值的方案。
用这种方式改造后,类库处理同步函数时的性能就能回到和直接调用同步函数几乎一致的水平。
内容的提问来源于stack exchange,提问作者user354490
相关产品推荐
相关产品推荐

