Skip to content

chore: change async document - #45

Merged
Yash-pluto merged 1 commit into
Yash-pluto:mainfrom
Shraddha-Rawat:feat/shraddha/doc/async
Aug 11, 2026
Merged

Yash-pluto merged 1 commit into
Yash-pluto:mainfrom
Shraddha-Rawat:feat/shraddha/doc/async

Conversation

@Shraddha-Rawat

@Shraddha-Rawat Shraddha-Rawat commented Aug 11, 2026 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Documentation
    • Expanded the asynchronous programming guide with comprehensive coverage of promises, async/await, event loops, concurrency, streaming, cancellation, error handling, retries, and rate limiting.
    • Added practical examples, API guidance, design patterns, testing and debugging advice, security considerations, reference material, and checklists.

@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the vardhanyash3105-1066's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The async programming page was expanded from a short introduction into a comprehensive guide. It now covers JavaScript runtime behavior, APIs, concurrency, cancellation, reliability patterns, testing, security, practical examples, references, and checklists.

Changes

Async Programming Documentation

Layer / File(s) Summary
Async foundations
frontend/content/async.mdx
The page now explains promise states, handlers, combinators, async functions, await, and error propagation.
Runtime and API behavior
frontend/content/async.mdx
The page covers event-loop scheduling, browser and Node.js APIs, concurrency, streaming, iteration, and backpressure.
Cancellation and control patterns
frontend/content/async.mdx
The page adds cancellation, timeouts, cleanup, retries, higher-order helpers, and concurrency limits.
Production practices and testing
frontend/content/async.mdx
The page adds guidance for data fetching, performance, testing, debugging, security, API design, compatibility, and common pitfalls.
Examples and reference material
frontend/content/async.mdx
The page adds practical scenarios, pattern comparisons, API references, glossary material, exercises, resources, and checklists.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Possibly related PRs

  • Yash-pluto/refme#38: Both changes modify frontend/content/async.mdx; this PR expands the guide introduced there.

Suggested reviewers: nikhil-phoenix

Poem

Promises gather, timers hum,
Awaiting tasks now safely run.
Streams flow clear through every queue,
Retries and cancellation too.
A wider guide now charts the way.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title identifies the main change as an update to the async documentation, although it is somewhat broad.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/content/async.mdx`:
- Around line 642-656: Prevent both retry helpers from resolving undefined when
attempts is less than 1. In frontend/content/async.mdx lines 642-656, add
attempts validation at the start of withRetry or throw lastError after the loop;
apply the same terminal handling in withExponentialBackoff at lines 663-678,
preserving normal retry behavior for valid attempt counts.
- Around line 1129-1132: Update the “Unhandled Rejections” text in the async MDX
content to add the missing article at the referenced sentence, and replace the
double backticks around callback hell with single backticks for inline code.
Preserve the surrounding Markdown and ensure the MDX file continues to meet its
existing formatting requirements.
- Around line 1366-1373: Update poll so the delay created after await fn()
observes the provided signal and settles immediately when signal.aborted,
instead of always waiting for the full interval. Preserve the existing loop
condition and polling behavior when the signal remains active.
- Around line 1512-1513: Update the worker API names in the documentation list
to identify Node.js’s `Worker` export from `node:worker_threads`, and remove the
nonexistent `WorkerThread` entry.
- Around line 440-454: Update processBatch to process items in bounded chunks
and yield to the event loop between chunks. Guard withRetry against attempts
below one by rejecting or throwing instead of returning undefined. Make
limitConcurrency asynchronous and remove executing entries in finally so
fulfilled and rejected tasks release slots while preserving rejection
propagation. Change getCache to memoize the initialization promise, clearing it
on failure to permit retries.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 26dcc79b-ea9f-476f-a822-70d160c0a66e

📥 Commits

Reviewing files that changed from the base of the PR and between 35362ed and ed556a4.

📒 Files selected for processing (1)
  • frontend/content/async.mdx

Comment on lines +440 to +454
### Cooperative Concurrency

Avoid long-running synchronous loops in async code.
Break large batches into smaller chunks or use timer-based yielding to keep the loop responsive.

```js
const fetchData = () =>
new Promise((resolve) => {
setTimeout(() => resolve("done"), 1000);
function processBatch(items) {
return new Promise((resolve) => {
setTimeout(() => {
items.forEach(handleItem);
resolve();
}, 0);
});
}
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

The processBatch sample does not yield cooperatively. The prose says to break large batches into smaller chunks. The code defers the whole loop by one macrotask, then runs items.forEach(handleItem) synchronously. The event loop still stalls for the full batch. Show real chunking instead.

🐛 Proposed chunked implementation
-```js
-function processBatch(items) {
-  return new Promise((resolve) => {
-    setTimeout(() => {
-      items.forEach(handleItem);
-      resolve();
-    }, 0);
-  });
-}
-```
+```js
+const yieldToEventLoop = () => new Promise((resolve) => setTimeout(resolve, 0));
+
+async function processBatch(items, chunkSize = 100) {
+  for (let i = 0; i < items.length; i += chunkSize) {
+    items.slice(i, i + chunkSize).forEach(handleItem);
+    await yieldToEventLoop();
+  }
+}
+```
</details>
</review_comment>



<review_comment line_ranges="642-656">
**`withRetry` resolves `undefined` when `attempts` is less than 1.** The loop body never executes, so the helper silently fulfills with `undefined` instead of failing. Readers copy this helper directly. Guard the input or throw after the loop.





<details>
<summary>🛡️ Proposed guard</summary>

```diff
 const withRetry = (operation, attempts = 3) => async (...args) => {
+  if (attempts < 1) {
+    throw new RangeError("attempts must be at least 1");
+  }
   let lastError;
   for (let i = 0; i < attempts; i += 1) {

<review_comment line_ranges="684-705">
limitConcurrency is a syntax error: await inside a non-async function. Line 685 declares a plain arrow function. Line 699 uses await Promise.race(executing). This sample does not parse.

A second defect follows the same fix. The .then on line 690 removes the task from executing only on fulfillment. If a task rejects, its promise stays in executing forever. Once limit rejections accumulate, Promise.race resolves immediately on the stale settled promises and the concurrency cap stops working. Use finally so both outcomes release the slot.

🐛 Proposed fix
-const limitConcurrency = (tasks, limit) => {
+const limitConcurrency = async (tasks, limit) => {
   const results = [];
   const executing = [];
 
   for (const task of tasks) {
-    const promise = task().then((result) => {
-      executing.splice(executing.indexOf(promise), 1);
-      return result;
-    });
+    const promise = task().finally(() => {
+      executing.splice(executing.indexOf(promise), 1);
+    });
 
     results.push(promise);
     executing.push(promise);
 
     if (executing.length >= limit) {
       await Promise.race(executing);
     }
   }
 
   return Promise.all(results);
 };

Note: promise.finally() keeps the rejection, so Promise.all(results) still surfaces it. Attach a no-op catch to the executing copy if you want to avoid an unhandled-rejection warning while the pool drains.

<review_comment line_ranges="1320-1333">
getCache does not memoize under concurrency. The prose promises memoization. The code assigns cache only after initializeCache() settles. Concurrent callers all pass the !cache check first, so initializeCache() runs once per caller. Cache the promise, not the resolved value.

🐛 Proposed fix
-```js
-let cache;
-async function getCache() {
-  if (!cache) {
-    cache = await initializeCache();
-  }
-  return cache;
-}
-```
+```js
+let cachePromise;
+function getCache() {
+  cachePromise ??= initializeCache().catch((error) => {
+    cachePromise = undefined; // allow a retry on failure
+    throw error;
+  });
+  return cachePromise;
+}
+```
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion
### Cooperative Concurrency

Avoid long-running synchronous loops in async code.
Break large batches into smaller chunks or use timer-based yielding to keep the loop responsive.
Suggested change
### Cooperative Concurrency
Avoid long-running synchronous loops in async code.
Break large batches into smaller chunks or use timer-based yielding to keep the loop responsive.
```js
const fetchData = () =>
new Promise((resolve) => {
setTimeout(() => resolve("done"), 1000);
function processBatch(items) {
return new Promise((resolve) => {
setTimeout(() => {
items.forEach(handleItem);
resolve();
}, 0);
});
}
```
const withRetry = (operation, attempts = 3) => async (...args) => {
if (attempts < 1) {
throw new RangeError("attempts must be at least 1");
}
let lastError;
for (let i = 0; i < attempts; i += 1) {
Suggested change
### Cooperative Concurrency
Avoid long-running synchronous loops in async code.
Break large batches into smaller chunks or use timer-based yielding to keep the loop responsive.
```js
const fetchData = () =>
new Promise((resolve) => {
setTimeout(() => resolve("done"), 1000);
function processBatch(items) {
return new Promise((resolve) => {
setTimeout(() => {
items.forEach(handleItem);
resolve();
}, 0);
});
}
```
const limitConcurrency = async (tasks, limit) => {
const results = [];
const executing = [];
for (const task of tasks) {
const promise = task().finally(() => {
executing.splice(executing.indexOf(promise), 1);
});
results.push(promise);
executing.push(promise);
if (executing.length >= limit) {
await Promise.race(executing);
}
}
return Promise.all(results);
};
Suggested change
### Cooperative Concurrency
Avoid long-running synchronous loops in async code.
Break large batches into smaller chunks or use timer-based yielding to keep the loop responsive.
```js
const fetchData = () =>
new Promise((resolve) => {
setTimeout(() => resolve("done"), 1000);
function processBatch(items) {
return new Promise((resolve) => {
setTimeout(() => {
items.forEach(handleItem);
resolve();
}, 0);
});
}
```
let cachePromise;
function getCache() {
cachePromise ??= initializeCache().catch((error) => {
cachePromise = undefined; // allow a retry on failure
throw error;
});
return cachePromise;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/content/async.mdx` around lines 440 - 454, Update processBatch to
process items in bounded chunks and yield to the event loop between chunks.
Guard withRetry against attempts below one by rejecting or throwing instead of
returning undefined. Make limitConcurrency asynchronous and remove executing
entries in finally so fulfilled and rejected tasks release slots while
preserving rejection propagation. Change getCache to memoize the initialization
promise, clearing it on failure to permit retries.

Comment on lines 642 to +656
```js
const [data1, data2] = await Promise.all([
fetchData(),
fetchData(),
]);
const withRetry = (operation, attempts = 3) => async (...args) => {
let lastError;
for (let i = 0; i < attempts; i += 1) {
try {
return await operation(...args);
} catch (error) {
lastError = error;
if (i === attempts - 1) {
throw lastError;
}
}
}
};
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Both retry helpers can fulfill with undefined. The shared root cause is the same: the for loop is the only path that returns or throws, and neither helper has a terminal return or throw after it. If attempts is less than 1, each helper resolves undefined and hides the failure.

  • frontend/content/async.mdx#L642-L656: validate attempts at the top of withRetry, or throw lastError after the loop.
  • frontend/content/async.mdx#L663-L678: apply the same guard to withExponentialBackoff.
📍 Affects 1 file
  • frontend/content/async.mdx#L642-L656 (this comment)
  • frontend/content/async.mdx#L663-L678
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/content/async.mdx` around lines 642 - 656, Prevent both retry
helpers from resolving undefined when attempts is less than 1. In
frontend/content/async.mdx lines 642-656, add attempts validation at the start
of withRetry or throw lastError after the loop; apply the same terminal handling
in withExponentialBackoff at lines 663-678, preserving normal retry behavior for
valid attempt counts.

Comment on lines +1129 to +1132
### Unhandled Rejections

The runtime may terminate process or log noisy warnings for unhandled promise rejections.
Install a global rejection handler and fix the source of the rejection.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Two small text defects. Line 1201 uses double backticks around callback hell. Single backticks are correct for inline code. Line 1131 is missing an article.

📝 Proposed fix
-The runtime may terminate process or log noisy warnings for unhandled promise rejections.
+The runtime may terminate the process or log noisy warnings for unhandled promise rejections.
-- callback nesting or ``callback hell``
+- callback nesting, or "callback hell"

As per path instructions: "Ensure MDX files have proper frontmatter, clean Markdown formatting, and that code blocks specify a language."

Also applies to: 1199-1205

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/content/async.mdx` around lines 1129 - 1132, Update the “Unhandled
Rejections” text in the async MDX content to add the missing article at the
referenced sentence, and replace the double backticks around callback hell with
single backticks for inline code. Preserve the surrounding Markdown and ensure
the MDX file continues to meet its existing formatting requirements.

Source: Path instructions

Comment on lines +1366 to +1373
```js
async function poll(fn, interval, signal) {
while (!signal.aborted) {
await fn();
await new Promise((resolve) => setTimeout(resolve, interval));
}
}
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

poll ignores signal during the sleep. The setTimeout is not wired to the abort signal. After an abort, the loop still waits the full interval before it exits. Abort the delay too.

♻️ Proposed fix
 async function poll(fn, interval, signal) {
   while (!signal.aborted) {
     await fn();
-    await new Promise((resolve) => setTimeout(resolve, interval));
+    await new Promise((resolve) => {
+      const timer = setTimeout(done, interval);
+      function done() {
+        clearTimeout(timer);
+        signal.removeEventListener("abort", done);
+        resolve();
+      }
+      signal.addEventListener("abort", done, { once: true });
+    });
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/content/async.mdx` around lines 1366 - 1373, Update poll so the
delay created after await fn() observes the provided signal and settles
immediately when signal.aborted, instead of always waiting for the full
interval. Preserve the existing loop condition and polling behavior when the
signal remains active.

Comment on lines +1512 to +1513
- `Worker`
- `WorkerThread`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Node.js worker_threads module Worker class exported names

💡 Result:

In Node.js, the Worker class, part of the node:worker_threads module, extends the EventEmitter class [1][2]. It represents an independent JavaScript execution thread and exports several methods, properties, and events [3][2]. Key members of the Worker class include: Methods: - postMessage(value[, transferList]): Sends a message to the worker's thread. - terminate: Stops all JavaScript execution in the worker thread as soon as possible. - getHeapSnapshot: Returns a readable stream for a V8 heap snapshot of the worker. - ref: Opposite of unref; keeps the thread alive as long as it is referenced. - unref: Allows the thread to exit if it is the only remaining work in the event loop. Properties: - threadId: A unique integer identifier for the worker. - resourceLimits: An object containing the resource limits for the worker. - stdin: A writable stream if the worker was initialized with stdin enabled. - stdout: A readable stream if the worker was initialized with stdout enabled. - stderr: A readable stream if the worker was initialized with stderr enabled. Events: - message: Emitted when the worker receives a message. - messageerror: Emitted when a message cannot be deserialized. - error: Emitted if the worker thread throws an uncaught exception. - exit: Emitted when the worker stops. - online: Emitted when the worker thread has started executing JavaScript code. The Worker class is instantiated using the new Worker(filename[, options]) constructor [3][2]. Because it extends EventEmitter, it also inherits standard methods like on, once, and emit [1][2].

Citations:


🏁 Script executed:

sed -n '1,12p;1500,1520p' frontend/content/async.mdx
printf '\nOccurrences:\n'
rg -n --fixed-strings 'WorkerThread' frontend/content/async.mdx
printf '\nFence languages:\n'
rg -n '^```' frontend/content/async.mdx | tail -n 20

Repository: Yash-pluto/refme

Length of output: 1378


Disambiguate the worker API names. Node.js exports Worker from node:worker_threads; WorkerThread is not an API name.

📝 Proposed fix
- `Worker`
- `WorkerThread`
+ `Worker` (browser Web Worker)
+ `Worker` from `node:worker_threads` (Node.js)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- `Worker`
- `WorkerThread`
- `Worker` (browser Web Worker)
- `Worker` from `node:worker_threads` (Node.js)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/content/async.mdx` around lines 1512 - 1513, Update the worker API
names in the documentation list to identify Node.js’s `Worker` export from
`node:worker_threads`, and remove the nonexistent `WorkerThread` entry.

@Yash-pluto Yash-pluto left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @shraddharawatbnp-coder, I've checked the files.

@Yash-pluto
Yash-pluto merged commit 91c9247 into Yash-pluto:main Aug 11, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants