Skip to content

Commit 485c9d4

Browse files
authored
update: asynchronous-flow-control.md formatting with prettier
Signed-off-by: Ahmed Emad <[email protected]>
1 parent 035fe03 commit 485c9d4

1 file changed

Lines changed: 37 additions & 29 deletions

File tree

apps/site/pages/en/learn/asynchronous-work/asynchronous-flow-control.md

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,15 @@ async1(function (input, result1) {
3131
Of course, in real life there would most likely be additional lines of code to handle `result1`, `result2`, etc., thus, the length and complexity of this issue usually results in code that looks much more messy than the example above.
3232

3333
## The Modern Solution: [async/await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)
34-
To solve callback hell, modern JavaScript introduced async and await. This is syntactic sugar built on top of a concept called Promises, allowing you to write asynchronous code that looks and behaves like synchronous code. It makes complex flows much easier to reason about.
3534

36-
* An async function is a function that implicitly returns a Promise.
35+
To solve callback hell, modern JavaScript introduced async and await. This is syntactic sugar built on top of a concept called Promises, allowing you to write asynchronous code that looks and behaves like synchronous code. It makes complex flows much easier to reason about.
3736

38-
* The await keyword can only be used inside an async function. It pauses the function's execution and waits for a Promise to be resolved, then resumes with the resolved value.
37+
- An async function is a function that implicitly returns a Promise.
3938

39+
- The await keyword can only be used inside an async function. It pauses the function's execution and waits for a Promise to be resolved, then resumes with the resolved value.
4040

4141
Let's rewrite the "callback hell" example using async/await. Notice how flat and readable it becomes:
42+
4243
```js
4344
async function performOperations() {
4445
try {
@@ -54,6 +55,7 @@ async function performOperations() {
5455
}
5556
}
5657
```
58+
5759
This code is executed sequentially from top to bottom, just like synchronous code, but without blocking the main thread.
5860

5961
**Thinking in Functions**
@@ -75,6 +77,7 @@ Network requests can be incoming requests initiated by a foreign network, by ano
7577
A middleware function will return another function, and a terminator function will invoke the callback. The following illustrates the flow to network or file system requests. Here the latency is 0 because all these values are available in memory.
7678

7779
Here’s how we can structure a simple flow using async functions. Each function passes its result to the next.
80+
7881
```js
7982
async function final(someInput) {
8083
return `${someInput} and terminated.`;
@@ -86,7 +89,7 @@ async function middleware(someInput) {
8689
}
8790

8891
async function initiate() {
89-
const someInput = 'hello this is a function, ';
92+
const someInput = "hello this is a function, ";
9093
// We await the result of the entire chain.
9194
const result = await middleware(someInput);
9295
console.log(result);
@@ -113,7 +116,7 @@ If an object is available in memory, iteration is possible, and there will not b
113116

114117
```js
115118
function getSong() {
116-
let _song = '';
119+
let _song = "";
117120
let i = 100;
118121
for (i; i > 0; i -= 1) {
119122
_song += `${i} beers on the wall, you take one down and pass it around, ${i - 1} bottles of beer on the wall\n`;
@@ -139,7 +142,7 @@ However, if the data exists outside of memory the iteration will no longer work:
139142

140143
```js
141144
function getSong() {
142-
let _song = '';
145+
let _song = "";
143146
let i = 100;
144147
for (i; i > 0; i -= 1) {
145148
setTimeout(function () {
@@ -158,13 +161,13 @@ function singSong(_song) {
158161
console.log(_song);
159162
}
160163

161-
const song = getSong('beer');
164+
const song = getSong("beer");
162165
// this will not work
163166
singSong(song);
164167
// Uncaught Error: song is '' empty, FEED ME A SONG!
165168
```
166169

167-
Why did this happen? setTimeout (like file system or network requests) instructs the Node.js event loop to schedule the provided function for execution at a later time. The for loop completes almost instantly, and _song (which is still an empty string) is returned immediately. The functions scheduled by setTimeout run much later, long after singSong has attempted to use the empty _song.
170+
Why did this happen? setTimeout (like file system or network requests) instructs the Node.js event loop to schedule the provided function for execution at a later time. The for loop completes almost instantly, and \_song (which is still an empty string) is returned immediately. The functions scheduled by setTimeout run much later, long after singSong has attempted to use the empty \_song.
168171

169172
The main thread cannot be blocked indefinitely while waiting for I/O or other asynchronous tasks. Fortunately, Promises and async/await provide the mechanisms to explicitly wait for these operations to complete before continuing, allowing us to manage asynchronous control flow effectively.
170173

@@ -174,13 +177,14 @@ You will be able to perform almost all of your operations with the following 3 p
174177

175178
```js
176179
// Simulate an asynchronous operation and return a Promise.
177-
const simulateAsyncOp = (id, durationMs) => new Promise(resolve => {
178-
console.log(`[${id}] Starting operation.`);
179-
setTimeout(() => {
180-
console.log(`[${id}] Finished operation.`);
181-
resolve(`Operation ${id} complete.`);
182-
}, durationMs);
183-
});
180+
const simulateAsyncOp = (id, durationMs) =>
181+
new Promise((resolve) => {
182+
console.log(`[${id}] Starting operation.`);
183+
setTimeout(() => {
184+
console.log(`[${id}] Finished operation.`);
185+
resolve(`Operation ${id} complete.`);
186+
}, durationMs);
187+
});
184188

185189
const operations = [
186190
() => simulateAsyncOp(1, 500),
@@ -202,14 +206,15 @@ async function executeInSeries(asyncFunctions) {
202206
await executeInSeries(operations);
203207
})();
204208
```
209+
205210
**Applying "In Series": The Beer Song Solution:** The "In Series" pattern is precisely what's needed to fix the song generation, it makes sure that each line is created then added in the correct order.
206211

207212
```js
208213
async function getSong() {
209214
const _songParts = [];
210215
for (let i = 100; i > 0; i -= 1) {
211216
// Await for each line.
212-
const line = await new Promise(resolve => {
217+
const line = await new Promise((resolve) => {
213218
setTimeout(() => {
214219
let currentLine = `${i} beers on the wall, you take one down and pass it around, ${
215220
i - 1
@@ -222,7 +227,7 @@ async function getSong() {
222227
});
223228
_songParts.push(line);
224229
}
225-
return _songParts.join('');
230+
return _songParts.join("");
226231
}
227232

228233
function singSong(songContent) {
@@ -242,14 +247,15 @@ function singSong(songContent) {
242247

243248
```js
244249
// Simulate an asynchronous task.
245-
const processItem = (id) => new Promise(resolve => {
246-
const delay = Math.random() * 500 + 50;
247-
console.log(`[Item ${id}] Starting.`);
248-
setTimeout(() => {
249-
console.log(`[Item ${id}] Finished.`);
250-
resolve(`Item ${id} processed.`);
251-
}, delay);
252-
});
250+
const processItem = (id) =>
251+
new Promise((resolve) => {
252+
const delay = Math.random() * 500 + 50;
253+
console.log(`[Item ${id}] Starting.`);
254+
setTimeout(() => {
255+
console.log(`[Item ${id}] Finished.`);
256+
resolve(`Item ${id} processed.`);
257+
}, delay);
258+
});
253259

254260
// An array of samples
255261
const itemsToProcess = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
@@ -259,7 +265,9 @@ async function processLimitedInSeries(items, limit) {
259265
const queue = [...items];
260266
const active = new Set(); // Tracks currently running promises.
261267

262-
console.log(`\n--- Starting Limited In Series Execution (Limit: ${limit}) ---`);
268+
console.log(
269+
`\n--- Starting Limited In Series Execution (Limit: ${limit}) ---`,
270+
);
263271

264272
while (queue.length > 0 || active.size > 0) {
265273
while (active.size < limit && queue.length > 0) {
@@ -326,8 +334,8 @@ Each has its own use cases, benefits, and issues you can experiment and read abo
326334

327335
### Choosing the Right Pattern
328336

329-
* **In Series:** Use when order is critical, or when each task depends on the previous one (e.g., chained database operations).
337+
- **In Series:** Use when order is critical, or when each task depends on the previous one (e.g., chained database operations).
330338

331-
* **Limited in Series:** Use when you need concurrency but must control resource load or adhere to external rate limits (e.g., API calls to a throttled service).
339+
- **Limited in Series:** Use when you need concurrency but must control resource load or adhere to external rate limits (e.g., API calls to a throttled service).
332340

333-
* **Full Parallel:** Use when operations are independent and can run simultaneously for maximum throughput (e.g., fetching data from multiple unrelated sources).
341+
- **Full Parallel:** Use when operations are independent and can run simultaneously for maximum throughput (e.g., fetching data from multiple unrelated sources).

0 commit comments

Comments
 (0)