for this reason i always optimize the shit out of all synchronous code before resorting to async. and if you do need to go async after that, you might be better off just offloading that optimized synchronous op to a worker thread (or to wasm) to not block the UI.
modern JS vms are insanely fast when you pay attention to GC pressure, mem allocation, monomorphism, and dont use accidentally quadratic algos. it's rare that i encounter a codebase that can't be sped up by some large multiple without ever resorting to an async/defer crutch.