I'm a career programmer, very comfortable writing programs in Python, and recently started learning Node.
I understand the asynchronous features are useful in many situations, but when I debug my code, I find myself adding await
before every single statement (including debug log statements), to be absolutely sure the program is doing what I expect, and is outputting logs in the order I expect so that I can see what is happening.
I always want my code to execute synchronously. Is there a better way to achieve this than adding await
at the start of every line?
2 Answers 2
Coding synchronously or asynchronously is determined by the deepest function call in a call stack, to put it naively. Callers don't determine if code runs synchronously. The authors of the functions you call determine this by marking the function async
and returning Promise objects. The downstream affect is best described in What Color is Your Function? As soon as your function needs to call something asynchronously, your function needs to be marked async
, because it must return a Promise. Now anyone calling your function needs to handle this change in function signature.
So, the way to program synchronously is to not call async functions.
Promises in JavaScript do give you a way out of this mess. You can invoke the .then()
callback on the promise. Your function will not be async
, but it will also not be synchronous. JavaScript is full of these weird situations.
Consider these two code snippets:
Using Async and Await
async function calculate(num) {
let result = await someFunction();
let total = num * result.multiplier;
return total;
}
let sumTotal = await calculate(4);
alert("sum total is: " + sumTotal);
The await
keyword spreads everywhere, but each async function call is a clean one-liner. Compare that to code which uses promises, but does not use await
:
let sumTotal = 0;
calculate(4).then(result => {
sumTotal = result;
alert("sum total is: " + sumTotal);
});
You start building nested callbacks to Promise.then()
. The second example uses synchronous code, but still executes asynchronously. You just can't seem to escape the asynchronous part. More vexingly, beware that the result of your promise can be available independently of when you want to use that result. Consider this code:
Using Promises and Callbacks
let sumTotal = 0;
calculate(4).then(result => {
sumTotal = result;
});
// Alerts "sum total is 0"
alert("sum total is: " + sumTotal);
Race conditions can make your code execute out of order. In the code above, you could get sum total is 0
or sum total is 552
depending on how fast the promise is resolved from the calculate
function.
GeeksForGeeks.org has a good comparison of the two ways to call functions. Even though it is geared towards the NodeJS runtime, it applies equally to web browsers:
Promise | Async/Await |
---|---|
Promise is an object representing intermediate state of operation which is guaranteed to complete its execution at some point in future. | Async/Await is a syntactic sugar for promises, a wrapper making the code execute more synchronously. |
Promise has 3 states – resolved, rejected and pending. | It does not have any states. It returns a promise either resolved or rejected. |
If the function "fxn1" is to executed after the promise, then promise.then(fxn1) continues execution of the current function after adding the fxn1 call to the callback chain. | If the function "fxn1" is to executed after await, then await X() suspends execution of the current function and then fxn1 is executed. |
Error handling is done using .then() and .catch() methods. | Error handling is done using .try() and .catch() methods. |
Promise chains can become difficult to understand sometimes. | Using Async/Await makes it easier to read and understand the flow of the program as compared to promise chains. |
Source: Difference between Promise and async/await in Node | GeeksForGeeks.org
Strictly writing synchronous code means avoiding calling async functions or functions that return promises, otherwise you are stuck with asynchronous code one way or the other.
Is there a better way to achieve this than adding await at the start of every line?
Consider observer design pattern. It fits well with event driven architecture. Beware of callback hell.
Other options are strategy and chain of responsibility design patterns.
How can I code synchronous programs in Node?
Keep the number of events low, avoid perpetuating asynchronousness by using
- decision trees or procedural code.
- Replace the use of
await
andasync
with an implementation of observer design pattern turning the asynchronous part in an event source. - Subscribe to the event with chain of responsibility.
-
I feel like this answer has some good suggestions, but it could use a little cleaning up. Can you edit your answer to break up long sentences, add punctuation, and clarify how some of these design patterns could apply to the question?Greg Burghardt– Greg Burghardt2024年06月08日 23:44:40 +00:00Commented Jun 8, 2024 at 23:44
-
But callbacks are also asynchronous, so what's the point?Basilevs– Basilevs2024年07月14日 12:22:30 +00:00Commented Jul 14, 2024 at 12:22
Explore related questions
See similar questions with these tags.
await
things that don't return promises, but doing so isn't a major problem (details: stackoverflow.com/q/55262996/3001761).await
is the closest thing to synchronous execution you will get.