Is it a bad idea to use async/await in a Node/Express server?
Asked Answered
S

4

8

I have a NodeJS/Express web app, where TypeOrm is used for many database functions. To avoid callback hell I usually use async/await to call and wait for database actions from my endpoint methods.
I've heard, however, that methods like fs.readFileSync should always be avoided, since they are blocking and will force all other requests to wait. Does this also apply to async/await? Do I have to use promises and callbacks to get decent multi-user performance?

Steadfast answered 16/8, 2019 at 16:59 Comment(2)
Simply put, async and await are just syntax sugar around Promises. Your question becomes "Is it a bad idea to use Promises in a Node/Express server?", to which the answer is definite: No, it's not a bad idea. Promises have mitigated the infamous "callback hell", and in many cases, async/await make Promise-based code even cleaner.Postmark
@user633183: the OP could possibly clarify that further but I don't think their question is about promises vs callbacks but rather sync vs async (promises and callbacks mentioned in the very last sentence).Plantation
C
13

Sync functions really BLOCK the event loop, until the io is complete. But in other hand async-await is just syntactic sugar to the Promise chaining. It is not actually synchronous, it just looks like it. That is the biggest difference you need to understand.

But, Some problems are introduces with async-await making the promises too sequential.

For example, two independent promises should be executed parallelly with Promise.all But when you use async-await you tend to do

await func1();
await func2();

So, logically you may make bottleneck yourself. But syntactically it has no problems like Sync ones whatsoever.

You can check out ES5 transpilation using Babel REPL, you may understand a little bit better.

Chubb answered 16/8, 2019 at 17:32 Comment(1)
Often times async calls depend on one another and need to be executed sequentially: const u = await getUser(username); const posts = await getPosts(u.id). Independent async calls can use Promise.all but this doesn't preclude them from using await: const [a, b] = await Promise.all([ func1(), func2() ])Postmark
S
7

The reason you shouldn't use *Sync functions is that they block the event loop. That causes your application to become irresponsive while synchronous functions are being executed.

Promises help you avoid the callback hell problem when you are dealing with async code. Additionally, async/await syntax allows you to write asynchronous code that LOOKS like synchronous code. So it's perfectly fine to use async and await.

Stultz answered 16/8, 2019 at 17:27 Comment(0)
P
2

I've heard, however, that methods like fs.readFileSync should always be avoided, since they are blocking and will force all other requests to wait.

This is true, mostly.

Remember that your server doesn't run on a single pipeline. Rather, you use the cluster API to run multiple worker processes side-by-side (where the number of cores of the server's CPU limits the number of worker processes that should be run).

In reality then, even if a single event loop is blocked by a synchronous IO and other requests that are assigned to the very same loop are forced to wait, other worker processes are still able to process incoming requests.

On the other hand, if you make a request await an IO operation, the loop is able to pick up another request and process it. But, there's a trade off.

Suppose first request comes, you await a fs.readFile. The second request comes and it's processed. But the second request doesn't wait for any IO, rather, it's a CPU-bound operation (a heavy calculation maybe?). The IO operation triggered by the first request completes but it has to wait until the second request completes and only then the continuation can be picked up by the event loop and the response can be sent back.

Do I have to use promises and callbacks to get decent multi-user performance?

A simple answer would be yes, however, be careful and monitor your app to not to fall in a pitfall (e.g. mixing IO requests with CPU intensive tasks where the performance of async IO could be worse from the client's perspective).

Plantation answered 16/8, 2019 at 17:51 Comment(0)
M
1

Using async/await in Node.js syntax is preferable to the alternatives, which are stock promises or especially callbacks. It allows for much cleaner code which is easier to understand and maintain. We used to have to use babel to transpile to access these in older times but they've been in Node for ages now so I'd recommend for people to use them.

Monarchal answered 28/1, 2020 at 20:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.