Hacker News new | ask | show | jobs
by tobr 1324 days ago
Not as if. You’re making a synchronous call async. And so it keeps spreading through your code. Op’s trick is certainly more complicated but looks like a smart way to support async cases but still letting synchronous calls stay synchronous.
2 comments

Hmm I see. So the value is in creating a kind of blocking promise. I can see how that might be useful in certain circumstances, but using blocking functionality isn't something you'd want to rely on in general.
No, the promise doesn't block, it just stays a promise. However, for synchronous calls, the Promise overhead is obviated.

In other words, the performance price of synchronous vs asynchronous calls is the price of a function call vs Promise implementation (i.e. event-loop machinery); the price of a function call, including the stack frame allocation, which is non-zero (recall the times that assembly programmers would dismiss languages like C as 'too-slow', having to allocate on function calls), versus pushing the Promise closure onto an event-loop, exiting the current event-loop, waiting for the next event-tick, popping off the next closure from the event stack, then creating the function call stack frame under a closure.

For inner-loops, the difference can be 20ms vs 20s.

I don't get it, the signature still returns `Type | Promise<Type>` how that promise doesn't spread through your code?

Still, the other comment about using await on plain values seems like a better option than parent comment

c-baby’s suggestion wraps a non-promise in a promise, so I don’t see how that’s still able to return a non-promise.

Awaiting plain values can only be done inside an async function, which means it returns a promise, which means you have to wait for the event loop to get the value out of there.

Generally I’m not aware of any other (reasonably ergonomic) way to write a single code path that can work with both sync and async input without itself always giving async output.