Repository: nodejs/nodejs.org
Pull request #7645: feat(learn): add article on promises
Author: login: avivkeller
Labels: name: content
description: Issues/pr concerning content
name: learn
description: Issues/pr concerning the learn section
Created: 2025-04-12T00:15:18Z | Merged: 2025-04-18T11:54:34Z

<!--
Please read the [Code of Conduct](https://github.com/nodejs/nodejs.org/blob/main/CODE_OF_CONDUCT.md) and the [Contributing Guidelines](https://github.com/nodejs/nodejs.org/blob/main/CONTRIBUTING.md) before opening a pull request.
-->

## Description

This PR adds an explanation of JavaScript / Node.js Promises to the website.

I took some feedback from #7639, and tried to incorporate specific examples and real-world scenarios.

## Related Issues

Fixes: #7200

### Check List

<!--
ATTENTION
Please follow this check list to ensure that you've followed all items before opening this PR
You can check the items by adding an `x` between the brackets, like this: `[x]`
-->

- [x] I have read the [Contributing Guidelines](https://github.com/nodejs/nodejs.org/blob/main/CONTRIBUTING.md) and made commit messages that follow the guideline.
- [x] I have run `npm run format` to ensure the code follows the style guide.
- [x] I have run `npm run test` to check if all tests are passing.
- [x] I have run `npx turbo build` to check if the website builds without errors.
- [x] I've covered new added functionality with unit tests if necessary.



Diff:
diff --git a/apps/site/navigation.json b/apps/site/navigation.json
index a764220103b07..f18d7fb9a25af 100644
--- a/apps/site/navigation.json
+++ b/apps/site/navigation.json
@@ -244,6 +244,10 @@
               "link": "/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks",
               "label": "components.navigation.learn.asynchronousWork.links.javascriptAsynchronousProgrammingAndCallbacks"
             },
+            "discoverPromisesInNodejs": {
+              "link": "/learn/asynchronous-work/discover-promises-in-nodejs",
+              "label": "components.navigation.learn.asynchronousWork.links.discoverPromisesInNodejs"
+            },
             "discoverJavascriptTimers": {
               "link": "/learn/asynchronous-work/discover-javascript-timers",
               "label": "components.navigation.learn.asynchronousWork.links.discoverJavascriptTimers"
diff --git a/apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md b/apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
new file mode 100644
index 0000000000000..363a9fc1e935d
--- /dev/null
+++ b/apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
@@ -0,0 +1,388 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Essentially, a Promise is a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+When you order the pizza, You're in the pending state, hungry and hopeful. If the pizza arrives hot and cheesy, you've entered the fulfilled state. But if the restaurant calls to say they've dropped your pizza on floor, you're in the rejected state.
+
+Regardless of whether your dinner ends in joy or disappointment, once there's a final outcome, the Promise is considered **settled**.
+
+## Basic Syntax of a Promise
+
+One of the most common ways to create a Promise is using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+If an error is thrown inside the executor function, the Promise will be rejected with that error.
+The return value of the executor function is ignored: only `resolve` or `reject` should be used to settle the Promise.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()`, `.catch()`, and `.finally()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()`, `.catch()`, and `.finally()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+- `.finally()` is used to handle a settled Promise, regardless of whether the Promise resolved or rejected.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  })
+  .finally(() => {
+    console.log('The promise has completed'); // This will run when the Promise is settled
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise = delay(1000).then(() => 'First task completed');
+
+promise
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return delay(1000).then(() => 'Second task completed'); // Return a second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword ensures that each Promise is settled before moving on to the next statement. This leads to a more linear and readable flow of asynchronous code.
+
+Essentially, the code above will execute the same as if the user wrote:
+
+```js
+promise1
+  .then(function (result1) {
+    console.log(result1);
+    return promise2;
+  })
+  .then(function (result2) {
+    console.log(result2);
+  })
+  .catch(function (error) {
+    console.log(error);
+  });
+```
+
+### Top-Level Await
+
+When using [ECMAScript Modules](https://nodejs.org/api/esm.html), the module itself is treated as a top-level scope that supports asynchronous operations natively. This means that you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```mjs
+import { setTimeout as delay } from 'node:timers/promises';
+
+await delay(1000);
+```
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### `Promise.all()`
+
+This method accepts an array of Promises and returns a new Promise that resolves once all the Promises are fulfilled. If any Promise is rejected, `Promise.all()` will immediately reject. However, even if rejection occurs, the Promises continue to execute. When handling a large number of Promises, especially in batch processing, using this function can strain the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### `Promise.allSettled()`
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### `Promise.race()`
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects. Regardless of which promise settles first, all promises are fully executed.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### `Promise.any()`
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 success');
+const api2 = delay(1000).then(() => 'API 2 success');
+const api3 = delay(1500).then(() => 'API 3 success');
+
+Promise.any([api1, api2, api3])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### `Promise.reject()` and `Promise.resolve()`
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+### `Promise.try()`
+
+`Promise.try()` is a method that executes a given function, whether it's synchronous or asynchronous, and wraps the result in a promise. If the function throws an error or returns a rejected promise, `Promise.try()` will return a rejected promise. If the function completes successfully, the returned promise will be fulfilled with its value.
+
+This can be particularly useful for starting promise chains in a consistent way, especially when working with code that might throw errors synchronously.
+
+```js
+function mightThrow() {
+  if (Math.random() > 0.5) {
+    throw new Error('Oops, something went wrong!');
+  }
+  return 'Success!';
+}
+
+Promise.try(mightThrow)
+  .then(result => {
+    console.log('Result:', result);
+  })
+  .catch(err => {
+    console.error('Caught error:', err.message);
+  });
+```
+
+In this example, `Promise.try()` ensures that if `mightThrow()` throws an error, it will be caught in the `.catch()` block, making it easier to handle both sync and async errors in one place.
+
+### `Promise.withResolvers()`
+
+This method creates a new promise along with its associated resolve and reject functions, and returns them in a convenient object. This is used, for example, when you need to create a promise but resolve or reject it later from outside the executor function.
+
+```js
+const { promise, resolve, reject } = Promise.withResolvers();
+
+setTimeout(() => {
+  resolve('Resolved successfully!');
+}, 1000);
+
+promise.then(value => {
+  console.log('Success:', value);
+});
+```
+
+In this example, `Promise.withResolvers()` gives you full control over when and how the promise is resolved or rejected, without needing to define the executor function inline. This pattern is commonly used in event-driven programming, timeouts, or when integrating with non-promise-based APIs.
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)) // Handles the rejection
+  .finally(error => console.log('Promise completed')); // Runs regardless of promise resolution
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### `queueMicrotask()`
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### `process.nextTick()`
+
+`process.nextTick()` is used to schedule a callback to be executed immediately after the current operation completes. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
+
+```js
+process.nextTick(() => {
+  console.log('Next tick callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### `setImmediate()`
+
+`setImmediate()` is used to execute a callback after the current event loop cycle finishes and all I/O events have been processed. This means that `setImmediate()` callbacks run after any I/O callbacks, but before timers.
+
+```js
+setImmediate(() => {
+  console.log('Immediate callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### When to Use Each
+
+- Use `queueMicrotask()` for tasks that need to run immediately after the current script and before any I/O or timer callbacks, typically for Promise resolutions.
+- Use `process.nextTick()` for tasks that should execute before any I/O events, often useful for deferring operations or handling errors synchronously.
+- Use `setImmediate()` for tasks that should run after I/O events but before timers.
+
+Because these tasks execute outside of the current synchronous flow, uncaught exceptions inside these callbacks won't be caught by surrounding `try/catch` blocks and may crash the application if not properly managed (e.g., by attaching `.catch()` to Promises or using global error handlers like `process.on('uncaughtException')`).
+
+For more information on the Event Loop, and the execution order of various phases, please see the related article, [The Node.js Event Loop](/learn/asynchronous-work/event-loop-timers-and-nexttick).
diff --git a/packages/i18n/locales/en.json b/packages/i18n/locales/en.json
index 43d3f91c69204..4865a0c3f945e 100644
--- a/packages/i18n/locales/en.json
+++ b/packages/i18n/locales/en.json
@@ -61,6 +61,7 @@
           "links": {
             "asynchronousWork": "Asynchronous Work",
             "asynchronousFlowControl": "Asynchronous flow control",
+            "discoverPromisesInNodejs": "Discover Promises in Node.js",
             "overviewOfBlockingVsNonBlocking": "Overview of Blocking vs Non-Blocking",
             "javascriptAsynchronousProgrammingAndCallbacks": "JavaScript Asynchronous Programming and Callbacks",
             "discoverJavascriptTimers": "Discover JavaScript Timers",


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 1 out of 3 changed files in this pull request and generated no comments.

<details>
<summary>Files not reviewed (2)</summary>

* **apps/site/navigation.json**: Language not supported
* **packages/i18n/locales/en.json**: Language not supported
</details>



state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T00:15:33Z
user: login: mcollina
body: This should also cover the relationship between promises, queueMicrotask, process.nextTick and setImmediate.
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-04-12T08:56:13Z
user: login: avivkeller
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T13:48:50Z
user: login: AugustinMauroy
body: Nice but nothing about await on top level
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T15:51:02Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:14:33Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:16:59Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:17:36Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:19:31Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:20:14Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:21:51Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:22:42Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:26:59Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:27:26Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:29:26Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:30:06Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:32:12Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:33:18Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:34:00Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:37:42Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:41:38Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T16:58:53Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T17:01:50Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T17:10:03Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T17:10:57Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T17:12:25Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T17:32:51Z
user: login: avivkeller
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T19:08:02Z
user: login: avivkeller
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T19:15:24Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T19:42:13Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T19:44:09Z
user: login: jasnell
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T20:36:49Z
user: login: avivkeller
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-12T20:52:17Z
user: login: jasnell
body: Let's ask @mcollina to review as well.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-13T16:18:02Z
user: login: AugustinMauroy
body: LGMT ! 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-17T19:37:17Z

Review comments:
diff_hunk: @@ -0,0 +1,264 @@
+---
+title: Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const promise1 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('First task completed'), 1000);
+});
+
+const promise2 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('Second task completed'), 1000);
+});
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+In this example:
+
+- The first Promise resolves after 1 second, and its result is logged.
+- The second Promise resolves after another second, and its result is logged after the first one finishes.
+
+## Using Async/Await with Promises
path: apps/site/pages/en/learn/asynchronous-work/promises-in-nodejs.md
user: login: mcollina
body: This whole paragraph is a bit too simplistic. async/await is a bit more complex than that.

You can refer to the talk/workshop @jasnell did when at NearForm: https://www.youtube.com/watch?v=XV-u_Ow47s0. I would recommend adding it as a reference, too.
created_at: 2025-04-12T08:53:30Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,264 @@
+---
+title: Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const promise1 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('First task completed'), 1000);
+});
+
+const promise2 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('Second task completed'), 1000);
+});
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+In this example:
+
+- The first Promise resolves after 1 second, and its result is logged.
+- The second Promise resolves after another second, and its result is logged after the first one finishes.
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until the Promise is resolved or rejected.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+```js
+const fetchData1 = new Promise(resolve =>
+  setTimeout(() => resolve('Data from API 1'), 1000)
+);
+const fetchData2 = new Promise(resolve =>
+  setTimeout(() => resolve('Data from API 2'), 2000)
+);
path: apps/site/pages/en/learn/asynchronous-work/promises-in-nodejs.md
user: login: mcollina
body: Please avoid recommending this pattern. use the equivalent from `node:timers/promises`
created_at: 2025-04-12T08:54:17Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,264 @@
+---
+title: Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const promise1 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('First task completed'), 1000);
+});
+
+const promise2 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('Second task completed'), 1000);
+});
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+In this example:
+
+- The first Promise resolves after 1 second, and its result is logged.
+- The second Promise resolves after another second, and its result is logged after the first one finishes.
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until the Promise is resolved or rejected.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+```js
+const fetchData1 = new Promise(resolve =>
+  setTimeout(() => resolve('Data from API 1'), 1000)
+);
+const fetchData2 = new Promise(resolve =>
+  setTimeout(() => resolve('Data from API 2'), 2000)
+);
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
path: apps/site/pages/en/learn/asynchronous-work/promises-in-nodejs.md
user: login: mcollina
body: What's the main difference in error handling between this and `Promise.all()`.
created_at: 2025-04-12T08:54:54Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,264 @@
+---
+title: Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const promise1 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('First task completed'), 1000);
+});
+
+const promise2 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('Second task completed'), 1000);
+});
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+In this example:
+
+- The first Promise resolves after 1 second, and its result is logged.
+- The second Promise resolves after another second, and its result is logged after the first one finishes.
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until the Promise is resolved or rejected.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
path: apps/site/pages/en/learn/asynchronous-work/promises-in-nodejs.md
user: login: mcollina
body: This should really mention the footgun that `Promise.all()` is in respect to memory handling.
created_at: 2025-04-12T08:55:24Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,264 @@
+---
+title: Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const promise1 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('First task completed'), 1000);
+});
+
+const promise2 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('Second task completed'), 1000);
+});
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+In this example:
+
+- The first Promise resolves after 1 second, and its result is logged.
+- The second Promise resolves after another second, and its result is logged after the first one finishes.
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until the Promise is resolved or rejected.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+```js
+const fetchData1 = new Promise(resolve =>
+  setTimeout(() => resolve('Data from API 1'), 1000)
+);
+const fetchData2 = new Promise(resolve =>
+  setTimeout(() => resolve('Data from API 2'), 2000)
+);
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const task1 = new Promise(resolve =>
+  setTimeout(() => resolve('Task 1 done'), 2000)
+);
+const task2 = new Promise(resolve =>
+  setTimeout(() => resolve('Task 2 done'), 1000)
+);
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const api1 = new Promise((_, reject) =>
+  setTimeout(() => reject('API 1 failed'), 1000)
+);
+const api2 = new Promise(resolve =>
+  setTimeout(() => resolve('API 2 success'), 500)
+);
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  }
+}
+
+performTask();
+```
path: apps/site/pages/en/learn/asynchronous-work/promises-in-nodejs.md
user: login: mcollina
body: How does finally fits?
created_at: 2025-04-12T08:55:39Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,264 @@
+---
+title: Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const promise1 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('First task completed'), 1000);
+});
+
+const promise2 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('Second task completed'), 1000);
+});
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+In this example:
+
+- The first Promise resolves after 1 second, and its result is logged.
+- The second Promise resolves after another second, and its result is logged after the first one finishes.
+
+## Using Async/Await with Promises
path: apps/site/pages/en/learn/asynchronous-work/promises-in-nodejs.md
user: login: avivkeller
body: @jasnell I've added your talk as a reference, just confirming that [we have permission](https://github.com/nodejs/nodejs.org/issues/7200#issuecomment-2564402143) to do so?
created_at: 2025-04-12T13:48:50Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Promises in Node.js
path: apps/site/pages/en/learn/asynchronous-work/promises-in-nodejs.md
user: login: AugustinMauroy
body: ```suggestion
title: Discover Promises in Node.js
```

We can start with a slightly catchier title 
created_at: 2025-04-12T15:50:01Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: Nit... two sentences one after the other starting with "Think of a Promise..." is bit awkward.
created_at: 2025-04-12T16:14:33Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: You use a pizza delivery example above then switch to an email example here. Likely better to just continue the pizza delivery theme.... When you order the pizza you're in the `Pending` state. When the pizza arrives you're in the `Fulfilled` state. If the Pizza delivery scooter breaks down on the way to your house and the pizza tragically falls to the ground, you're in the `Rejected` state... etc.
created_at: 2025-04-12T16:16:59Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: This is one way of creating a promise but not the only.
created_at: 2025-04-12T16:17:35Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: It's worth highlighting that the function passed to the `Promise` constructor is called immediately as part of constructing the `Promise`, and that any errors it may throw synchronously are caught and used to reject the promise.

It's also worth mentioning that this function should not return any value.
created_at: 2025-04-12T16:19:31Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: Should mention `finally(...)` in here as well.
created_at: 2025-04-12T16:20:13Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: Hmm... these aren't chained. The promises are waiting concurrently with each other. The *continuations* are chained but that's not what I imagine was intended here. Chained async operations run serially to one another, not concurrently.
created_at: 2025-04-12T16:21:50Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: The second sentence starting with `However, ...` is out of place here. Best to discuss top-level await in a separate section.
created_at: 2025-04-12T16:22:42Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: I'm not sure "pauses execution" is the right term to use here. async/await does not actually pause execution as much as it decomposes the function into a series of continuations. For instance, the example above logically decomposes into...

```js
promise1.then(function (result1) {
  console.log(result1);
  return promise2;
}).then(function (result2) {
  console.log(result2);
}).catch(function (error) {
  console.log(error);
});
```

When viewed this way you get a better sense of how this is operating.
created_at: 2025-04-12T16:26:58Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: ❤️ 
created_at: 2025-04-12T16:27:26Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: Perhaps a better explanation: This method takes an array of Promises and returns another Promise that is fulfilled when they all resolve, or is rejected as soon as one is rejected. 
created_at: 2025-04-12T16:29:25Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: The first sentence here is a bit repetitive of the previous paragraph.
created_at: 2025-04-12T16:30:06Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: Because so many people get this wrong, it's worth pointing out that while the `Promise.race(...)` is resolved or rejected when the first promise resolves/rejects, the other promises are still going... that is, the other tasks are not canceled when one promise wins the race. I've lost count of the number of bugs I've run into in the wild because people didn't realize this.
created_at: 2025-04-12T16:32:12Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: This example is probably better with a third promise in the mix.
created_at: 2025-04-12T16:33:18Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: `Promise.try(...)` was also recently added and is worth mentioning.
created_at: 2025-04-12T16:33:59Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed after the current operation completes, but before any other event loop phases, such as I/O events, timers, or Promises. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
+
+```js
+process.nextTick(() => {
+  console.log('Next tick callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **`setImmediate()`**:
+
+`setImmediate()` is used to execute a callback after the current event loop cycle finishes and all I/O events have been processed. This means that `setImmediate()` callbacks run after any I/O callbacks, but before timers and the next tick queue.
+
+```js
+setImmediate(() => {
+  console.log('Immediate callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **When to Use Each**:
+
+- Use `queueMicrotask()` for tasks that need to run immediately after the current script and before any I/O or timer callbacks, typically for Promise resolutions.
+- Use `process.nextTick()` for tasks that should execute before any I/O events, often useful for deferring operations or handling errors synchronously.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: It's likely worth pointing out that error handling between `process.nextTick(...)` and `queueMicrotask(...)` is quite different.
created_at: 2025-04-12T16:37:42Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed after the current operation completes, but before any other event loop phases, such as I/O events, timers, or Promises. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
+
+```js
+process.nextTick(() => {
+  console.log('Next tick callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **`setImmediate()`**:
+
+`setImmediate()` is used to execute a callback after the current event loop cycle finishes and all I/O events have been processed. This means that `setImmediate()` callbacks run after any I/O callbacks, but before timers and the next tick queue.
+
+```js
+setImmediate(() => {
+  console.log('Immediate callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **When to Use Each**:
+
+- Use `queueMicrotask()` for tasks that need to run immediately after the current script and before any I/O or timer callbacks, typically for Promise resolutions.
+- Use `process.nextTick()` for tasks that should execute before any I/O events, often useful for deferring operations or handling errors synchronously.
+- Use `setImmediate()` for tasks that should run after I/O events but before timers.
+
+In short, the execution order is as follows:
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: This is not always true. When loading an ESM that uses `process.nextTick(...)` and `queueMicrotask(...)` at the top-level, the queued microtasks will run *first* ... actually this is true in any case where these are used in a promise continuation.

![image](https://github.com/user-attachments/assets/080ded9e-8abc-4a51-a160-77cf7def4231)

the reason is that microtasks scheduled while draining the microtask queue will also be drained at the same time.
created_at: 2025-04-12T16:41:38Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed after the current operation completes, but before any other event loop phases, such as I/O events, timers, or Promises. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
+
+```js
+process.nextTick(() => {
+  console.log('Next tick callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **`setImmediate()`**:
+
+`setImmediate()` is used to execute a callback after the current event loop cycle finishes and all I/O events have been processed. This means that `setImmediate()` callbacks run after any I/O callbacks, but before timers and the next tick queue.
+
+```js
+setImmediate(() => {
+  console.log('Immediate callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **When to Use Each**:
+
+- Use `queueMicrotask()` for tasks that need to run immediately after the current script and before any I/O or timer callbacks, typically for Promise resolutions.
+- Use `process.nextTick()` for tasks that should execute before any I/O events, often useful for deferring operations or handling errors synchronously.
+- Use `setImmediate()` for tasks that should run after I/O events but before timers.
+
+In short, the execution order is as follows:
+
+1. **Synchronous code** (e.g., regular function calls and script code)
+2. **`process.nextTick()`** callbacks
+3. **Microtasks** (e.g., Promises, `queueMicrotask()`)
+4. **Timers** (e.g., `setTimeout()`, `setInterval()`)
+5. **I/O callbacks** (e.g., network and file system operations)
+6. **`setImmediate()`** callbacks
+7. **Close callbacks** (e.g., `socket.on('close')`)
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: It's worth noting that Node.js will typically use `process.nextTick` to schedule events like `close` and `error`, etc. This might be a bit misleading as is. The reason a `close` event often occurs in this order is because an `I/O` callback schedules a `process.nextTick(...)` to emit the event. 
created_at: 2025-04-12T16:58:53Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed after the current operation completes, but before any other event loop phases, such as I/O events, timers, or Promises. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
+
+```js
+process.nextTick(() => {
+  console.log('Next tick callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **`setImmediate()`**:
+
+`setImmediate()` is used to execute a callback after the current event loop cycle finishes and all I/O events have been processed. This means that `setImmediate()` callbacks run after any I/O callbacks, but before timers and the next tick queue.
+
+```js
+setImmediate(() => {
+  console.log('Immediate callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **When to Use Each**:
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: It is probably worth stressing that the specific ordering of these is runtime implementation specific... that is, everything about the timing here is very specific to Node.js. While other runtimes might get close, none of the Node.js compatible runtimes adhere to the same ordering on these. For instance, Cloudflare Workers implements `process.nextTick(...)` simply by deferring to `queueMicrotask(...)` (that is, `process.nextTick` is really just an alias for `queueMicrotask`. There are actually quite a few timing differences between the runtimes.
created_at: 2025-04-12T17:01:49Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed after the current operation completes, but before any other event loop phases, such as I/O events, timers, or Promises. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
+
+```js
+process.nextTick(() => {
+  console.log('Next tick callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **`setImmediate()`**:
+
+`setImmediate()` is used to execute a callback after the current event loop cycle finishes and all I/O events have been processed. This means that `setImmediate()` callbacks run after any I/O callbacks, but before timers and the next tick queue.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: The last part of this sentence `... and the next tick queue` is not correct. Draining the next tick queue is independent of the event loop, and the next tick queue can be drained any number of times at each phase of the event loop where user code ends up running.
created_at: 2025-04-12T17:10:03Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed after the current operation completes, but before any other event loop phases, such as I/O events, timers, or Promises. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: This is inaccurate. The draining of the next tick queue is independent of the event loop.
created_at: 2025-04-12T17:10:57Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: Also, it is worth mentioning `Promise.withResolvers()` in here also.
created_at: 2025-04-12T17:12:24Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,264 @@
+---
+title: Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const promise1 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('First task completed'), 1000);
+});
+
+const promise2 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('Second task completed'), 1000);
+});
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+In this example:
+
+- The first Promise resolves after 1 second, and its result is logged.
+- The second Promise resolves after another second, and its result is logged after the first one finishes.
+
+## Using Async/Await with Promises
path: apps/site/pages/en/learn/asynchronous-work/promises-in-nodejs.md
user: login: jasnell
body: No need to ask. Feel free to use any of my talks/write ups.
created_at: 2025-04-12T17:32:51Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed after the current operation completes, but before any other event loop phases, such as I/O events, timers, or Promises. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
+
+```js
+process.nextTick(() => {
+  console.log('Next tick callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **`setImmediate()`**:
+
+`setImmediate()` is used to execute a callback after the current event loop cycle finishes and all I/O events have been processed. This means that `setImmediate()` callbacks run after any I/O callbacks, but before timers and the next tick queue.
+
+```js
+setImmediate(() => {
+  console.log('Immediate callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **When to Use Each**:
+
+- Use `queueMicrotask()` for tasks that need to run immediately after the current script and before any I/O or timer callbacks, typically for Promise resolutions.
+- Use `process.nextTick()` for tasks that should execute before any I/O events, often useful for deferring operations or handling errors synchronously.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: avivkeller
body: How so?
created_at: 2025-04-12T19:08:02Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed after the current operation completes, but before any other event loop phases, such as I/O events, timers, or Promises. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: avivkeller
body: So, when looking at the execution order, `process.nextTick()` can execute at any time?
created_at: 2025-04-12T19:15:24Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed after the current operation completes, but before any other event loop phases, such as I/O events, timers, or Promises. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: If you consider this flow (image borrowed from one of platformatic's blog posts)... 
![image](https://github.com/user-attachments/assets/7ea4330e-1d34-4baf-a12f-bcdb44d0860c)

The nextTick and queueMicrotask queues are drained when the control flow returns from JavaScript back to the C++ block there. So basically, any time any callback is triggered by the event loop that causes JavaScript to be executed. That can happen many times at any stage of the event loop turn.
created_at: 2025-04-12T19:42:12Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,317 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Think of a Promise as a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+For example, imagine you're waiting for an email from a friend. You're in the pending state. If your friend replies, you've entered the fulfilled state. If the email bounces back, you are in the rejected state.
+
+## Basic Syntax of a Promise
+
+A Promise is created using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()` and `.catch()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()` and `.catch()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise1 = delay(1000).then(() => 'First task completed');
+const promise2 = delay(1000).then(() => 'Second task completed');
+
+promise1
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return promise2; // Return the second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles. However, in [ECMAScript Modules](https://nodejs.org/api/esm.html), you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword pauses execution until each Promise is settled (resolved or rejected). This leads to a more linear and readable flow of asynchronous code.
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method takes an array of Promises and resolves them all. It only resolves when all Promises are fulfilled. If any of the Promises is rejected, `Promise.all()` will reject immediately.
+
+`Promise.all()` resolves when all Promises are completed. If you have a large number of Promises, especially in situations like batch processing, it could overwhelm the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 failed');
+const api2 = delay(1000).then(() => 'API 2 success');
+
+Promise.any([api1, api2])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)); // Handles the rejection
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed after the current operation completes, but before any other event loop phases, such as I/O events, timers, or Promises. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
+
+```js
+process.nextTick(() => {
+  console.log('Next tick callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **`setImmediate()`**:
+
+`setImmediate()` is used to execute a callback after the current event loop cycle finishes and all I/O events have been processed. This means that `setImmediate()` callbacks run after any I/O callbacks, but before timers and the next tick queue.
+
+```js
+setImmediate(() => {
+  console.log('Immediate callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **When to Use Each**:
+
+- Use `queueMicrotask()` for tasks that need to run immediately after the current script and before any I/O or timer callbacks, typically for Promise resolutions.
+- Use `process.nextTick()` for tasks that should execute before any I/O events, often useful for deferring operations or handling errors synchronously.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: Just for example.. 
![image](https://github.com/user-attachments/assets/e6dc5142-dbb3-4330-aa06-0bf4774b62cc)

created_at: 2025-04-12T19:44:09Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,401 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Essentially, a Promise is a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+When you order the pizza, You're in the pending state, hungry and hopeful. If the pizza arrives hot and cheesy, you've entered the fulfilled state. But if the restaurant calls to say they've dropped your pizza on floor, you're in the rejected state.
+
+Regardless of whether your dinner ends in joy or disappointment, once there's a final outcome, the Promise is considered **settled**.
+
+## Basic Syntax of a Promise
+
+One of the most common ways to create a Promise is using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+If an error is thrown inside the executor function, the Promise will be rejected with that error.
+The return value of the executor function is ignored: only `resolve` or `reject` should be used to settle the Promise.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()`, `.catch()`, and `.finally()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()`, `.catch()`, and `.finally()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+- `.finally()` is used to handle a settled Promise, regardless of whether the Promise resolved or rejected.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  })
+  .finally(() => {
+    console.log('The promise has completed'); // This will run when the Promise is settled
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise = delay(1000).then(() => 'First task completed');
+
+promise
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return delay(1000).then(() => 'Second task completed'); // Return a second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword ensures that each Promise is settled before moving on to the next statement. This leads to a more linear and readable flow of asynchronous code.
+
+Essentially, the code above will execute the same as if the user wrote:
+
+```js
+promise1
+  .then(function (result1) {
+    console.log(result1);
+    return promise2;
+  })
+  .then(function (result2) {
+    console.log(result2);
+  })
+  .catch(function (error) {
+    console.log(error);
+  });
+```
+
+### Top-Level Await
+
+When using [ECMAScript Modules](https://nodejs.org/api/esm.html), the module itself is treated as a top-level scope that supports asynchronous operations natively. This means that you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```mjs
+import { setTimeout as delay } from 'node:timers/promises';
+
+await delay(1000);
+```
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method accepts an array of Promises and returns a new Promise that resolves once all the Promises are fulfilled. If any Promise is rejected, `Promise.all()` will immediately reject. However, even if rejection occurs, the Promises continue to execute. When handling a large number of Promises, especially in batch processing, using this function can strain the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects. Regardless of which promise settles first, all promises are fully executed.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 success');
+const api2 = delay(1000).then(() => 'API 2 success');
+const api3 = delay(1500).then(() => 'API 3 success');
+
+Promise.any([api1, api2, api3])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+### **`Promise.try()`**:
+
+`Promise.try()` is a method that executes a given function, whether it's synchronous or asynchronous, and wraps the result in a promise. If the function throws an error or returns a rejected promise, `Promise.try()` will return a rejected promise. If the function completes successfully, the returned promise will be fulfilled with its value.
+
+This can be particularly useful for starting promise chains in a consistent way, especially when working with code that might throw errors synchronously.
+
+```js
+function mightThrow() {
+  if (Math.random() > 0.5) {
+    throw new Error('Oops, something went wrong!');
+  }
+  return 'Success!';
+}
+
+Promise.try(mightThrow)
+  .then(result => {
+    console.log('Result:', result);
+  })
+  .catch(err => {
+    console.error('Caught error:', err.message);
+  });
+```
+
+In this example, `Promise.try()` ensures that if `mightThrow()` throws an error, it will be caught in the `.catch()` block, making it easier to handle both sync and async errors in one place.
+
+### **`Promise.withResolvers()`**:
+
+This method creates a new promise along with its associated resolve and reject functions, and returns them in a convenient object. This is used, for example, when you need to create a promise but resolve or reject it later from outside the executor function.
+
+```js
+const { promise, resolve, reject } = Promise.withResolvers();
+
+setTimeout(() => {
+  resolve('Resolved successfully!');
+}, 1000);
+
+promise.then(value => {
+  console.log('Success:', value);
+});
+```
+
+In this example, `Promise.withResolvers()` gives you full control over when and how the promise is resolved or rejected, without needing to define the executor function inline. This pattern is commonly used in event-driven programming, timeouts, or when integrating with non-promise-based APIs.
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)) // Handles the rejection
+  .finally(error => console.log('Promise completed')); // Runs regardless of promise resolution
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed immediately after the current operation completes. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
+
+```js
+process.nextTick(() => {
+  console.log('Next tick callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **`setImmediate()`**:
+
+`setImmediate()` is used to execute a callback after the current event loop cycle finishes and all I/O events have been processed. This means that `setImmediate()` callbacks run after any I/O callbacks, but before timers.
+
+```js
+setImmediate(() => {
+  console.log('Immediate callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **When to Use Each**:
+
+- Use `queueMicrotask()` for tasks that need to run immediately after the current script and before any I/O or timer callbacks, typically for Promise resolutions.
+- Use `process.nextTick()` for tasks that should execute before any I/O events, often useful for deferring operations or handling errors synchronously.
+- Use `setImmediate()` for tasks that should run after I/O events but before timers.
+
+Because these tasks execute outside of the current synchronous flow, uncaught exceptions inside these callbacks won't be caught by surrounding `try/catch` blocks and may crash the application if not properly managed (e.g., by attaching `.catch()` to Promises or using global error handlers like `process.on('uncaughtException')`).
+
+In short, the execution order is as follows:
+
+1. **Synchronous code** (e.g., regular function calls and script code)
+2. **`process.nextTick()`** callbacks
+3. **Microtasks** (e.g., Promises, `queueMicrotask()`)
+   If a microtask queues another microtask, the new one is also executed before moving on.
+4. **Timers** (e.g., `setTimeout()`, `setInterval()`)
+5. **I/O callbacks** (e.g., network and file system operations)
+   Some operations, like `close` and `error` events, may use `process.nextTick()` internally and are executed in the next tick.
+6. **`setImmediate()`** callbacks
+
+`process.nextTick()` can execute at any stage in the execution order, as it is not bound by the event loop.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: jasnell
body: Sorry if I wasn't clear... this is *also* true of draining the microtask queue. We always drain both the next tick and microtask queue (in that order) at the same time.
created_at: 2025-04-12T20:36:48Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,401 @@
+---
+title: Discover Promises in Node.js
+layout: learn
+authors: avivkeller
+---
+
+# Discover Promises in Node.js
+
+A **Promise** is a special object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Essentially, a Promise is a placeholder for a value that is not yet available but will be in the future.
+
+Think of a Promise like ordering a pizza: you don't get it right away, but the delivery person promises to bring it to you later. You don't know _exactly_ when, but you know the outcome will either be "pizza delivered" or "something went wrong."
+
+## Promise States
+
+A Promise can be in one of three states:
+
+- **Pending**: The initial state, where the asynchronous operation is still running.
+- **Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
+- **Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
+
+When you order the pizza, You're in the pending state, hungry and hopeful. If the pizza arrives hot and cheesy, you've entered the fulfilled state. But if the restaurant calls to say they've dropped your pizza on floor, you're in the rejected state.
+
+Regardless of whether your dinner ends in joy or disappointment, once there's a final outcome, the Promise is considered **settled**.
+
+## Basic Syntax of a Promise
+
+One of the most common ways to create a Promise is using the `new Promise()` constructor. The constructor takes a function with two parameters: `resolve` and `reject`. These functions are used to transition the Promise from the **pending** state to either **fulfilled** or **rejected**.
+
+If an error is thrown inside the executor function, the Promise will be rejected with that error.
+The return value of the executor function is ignored: only `resolve` or `reject` should be used to settle the Promise.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+```
+
+In the above example:
+
+- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
+- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
+
+## Handling Promises with `.then()`, `.catch()`, and `.finally()`
+
+Once a Promise is created, you can handle the outcome by using the `.then()`, `.catch()`, and `.finally()` methods.
+
+- `.then()` is used to handle a fulfilled Promise and access its result.
+- `.catch()` is used to handle a rejected Promise and catch any errors that may occur.
+- `.finally()` is used to handle a settled Promise, regardless of whether the Promise resolved or rejected.
+
+```js
+const myPromise = new Promise((resolve, reject) => {
+  let success = true;
+
+  if (success) {
+    resolve('Operation was successful!');
+  } else {
+    reject('Something went wrong.');
+  }
+});
+
+myPromise
+  .then(result => {
+    console.log(result); // This will run if the Promise is fulfilled
+  })
+  .catch(error => {
+    console.error(error); // This will run if the Promise is rejected
+  })
+  .finally(() => {
+    console.log('The promise has completed'); // This will run when the Promise is settled
+  });
+```
+
+## Chaining Promises
+
+One of the great features of Promises is that they allow you to chain multiple asynchronous operations together. When you chain Promises, each `.then()` block waits for the previous one to complete before it runs.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const promise = delay(1000).then(() => 'First task completed');
+
+promise
+  .then(result => {
+    console.log(result); // 'First task completed'
+    return delay(1000).then(() => 'Second task completed'); // Return a second Promise
+  })
+  .then(result => {
+    console.log(result); // 'Second task completed'
+  })
+  .catch(error => {
+    console.error(error); // If any Promise is rejected, catch the error
+  });
+```
+
+## Using Async/Await with Promises
+
+One of the best ways to work with Promises in modern JavaScript is using **async/await**. This allows you to write asynchronous code that looks synchronous, making it much easier to read and maintain.
+
+- `async` is used to define a function that returns a Promise.
+- `await` is used inside an `async` function to pause execution until a Promise settles.
+
+```js
+async function performTasks() {
+  try {
+    const result1 = await promise1;
+    console.log(result1); // 'First task completed'
+
+    const result2 = await promise2;
+    console.log(result2); // 'Second task completed'
+  } catch (error) {
+    console.error(error); // Catches any rejection or error
+  }
+}
+
+performTasks();
+```
+
+In the `performTasks` function, the `await` keyword ensures that each Promise is settled before moving on to the next statement. This leads to a more linear and readable flow of asynchronous code.
+
+Essentially, the code above will execute the same as if the user wrote:
+
+```js
+promise1
+  .then(function (result1) {
+    console.log(result1);
+    return promise2;
+  })
+  .then(function (result2) {
+    console.log(result2);
+  })
+  .catch(function (error) {
+    console.log(error);
+  });
+```
+
+### Top-Level Await
+
+When using [ECMAScript Modules](https://nodejs.org/api/esm.html), the module itself is treated as a top-level scope that supports asynchronous operations natively. This means that you can use [`await` at the top level](https://nodejs.org/api/esm.html#top-level-await) without needing an `async` function.
+
+```mjs
+import { setTimeout as delay } from 'node:timers/promises';
+
+await delay(1000);
+```
+
+Async/await can be much more intricate than the simple examples provided. James Snell, a member of the Node.js Technical Steering Committee, has an [in-depth presentation](https://www.youtube.com/watch?v=XV-u_Ow47s0) that explores the complexities of Promises and async/await.
+
+## Promise-based Node.js APIs
+
+Node.js provides **Promise-based versions** of many of its core APIs, especially in cases where asynchronous operations were traditionally handled with callbacks. This makes it easier to work with Node.js APIs and Promises, and reduces the risk of "callback hell."
+
+For example, the `fs` (file system) module has a Promise-based API under `fs.promises`:
+
+```js
+const fs = require('node:fs').promises;
+// Or, you can import the promisified version directly:
+// const fs = require('node:fs/promises');
+
+async function readFile() {
+  try {
+    const data = await fs.readFile('example.txt', 'utf8');
+    console.log(data);
+  } catch (err) {
+    console.error('Error reading file:', err);
+  }
+}
+
+readFile();
+```
+
+In this example, `fs.promises.readFile()` returns a Promise, which we handle using `async/await` syntax to read the contents of a file asynchronously.
+
+## Advanced Promise Methods
+
+JavaScript's `Promise` global provides several powerful methods that help manage multiple asynchronous tasks more effectively:
+
+### **`Promise.all()`**:
+
+This method accepts an array of Promises and returns a new Promise that resolves once all the Promises are fulfilled. If any Promise is rejected, `Promise.all()` will immediately reject. However, even if rejection occurs, the Promises continue to execute. When handling a large number of Promises, especially in batch processing, using this function can strain the system's memory.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const fetchData1 = delay(1000).then(() => 'Data from API 1');
+const fetchData2 = delay(2000).then(() => 'Data from API 2');
+
+Promise.all([fetchData1, fetchData2])
+  .then(results => {
+    console.log(results); // ['Data from API 1', 'Data from API 2']
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
+```
+
+### **`Promise.allSettled()`**:
+
+This method waits for all promises to either resolve or reject and returns an array of objects that describe the outcome of each Promise.
+
+```js
+const promise1 = Promise.resolve('Success');
+const promise2 = Promise.reject('Failed');
+
+Promise.allSettled([promise1, promise2]).then(results => {
+  console.log(results);
+  // [ { status: 'fulfilled', value: 'Success' }, { status: 'rejected', reason: 'Failed' } ]
+});
+```
+
+Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure. It waits for all promises to settle, even if some reject. This provides better error handling for batch operations, where you may want to know the status of all tasks, regardless of failure.
+
+### **`Promise.race()`**:
+
+This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects. Regardless of which promise settles first, all promises are fully executed.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const task1 = delay(2000).then(() => 'Task 1 done');
+const task2 = delay(1000).then(() => 'Task 2 done');
+
+Promise.race([task1, task2]).then(result => {
+  console.log(result); // 'Task 2 done' (since task2 finishes first)
+});
+```
+
+### **`Promise.any()`**:
+
+This method resolves as soon as one of the Promises resolves. If all promises are rejected, it will reject with an `AggregateError`.
+
+```js
+const { setTimeout: delay } = require('node:timers/promises');
+
+const api1 = delay(2000).then(() => 'API 1 success');
+const api2 = delay(1000).then(() => 'API 2 success');
+const api3 = delay(1500).then(() => 'API 3 success');
+
+Promise.any([api1, api2, api3])
+  .then(result => {
+    console.log(result); // 'API 2 success' (since it resolves first)
+  })
+  .catch(error => {
+    console.error('All promises rejected:', error);
+  });
+```
+
+### **`Promise.reject()` and `Promise.resolve()`**:
+
+These methods create a rejected or resolved Promise directly.
+
+```js
+Promise.resolve('Resolved immediately').then(result => {
+  console.log(result); // 'Resolved immediately'
+});
+```
+
+### **`Promise.try()`**:
+
+`Promise.try()` is a method that executes a given function, whether it's synchronous or asynchronous, and wraps the result in a promise. If the function throws an error or returns a rejected promise, `Promise.try()` will return a rejected promise. If the function completes successfully, the returned promise will be fulfilled with its value.
+
+This can be particularly useful for starting promise chains in a consistent way, especially when working with code that might throw errors synchronously.
+
+```js
+function mightThrow() {
+  if (Math.random() > 0.5) {
+    throw new Error('Oops, something went wrong!');
+  }
+  return 'Success!';
+}
+
+Promise.try(mightThrow)
+  .then(result => {
+    console.log('Result:', result);
+  })
+  .catch(err => {
+    console.error('Caught error:', err.message);
+  });
+```
+
+In this example, `Promise.try()` ensures that if `mightThrow()` throws an error, it will be caught in the `.catch()` block, making it easier to handle both sync and async errors in one place.
+
+### **`Promise.withResolvers()`**:
+
+This method creates a new promise along with its associated resolve and reject functions, and returns them in a convenient object. This is used, for example, when you need to create a promise but resolve or reject it later from outside the executor function.
+
+```js
+const { promise, resolve, reject } = Promise.withResolvers();
+
+setTimeout(() => {
+  resolve('Resolved successfully!');
+}, 1000);
+
+promise.then(value => {
+  console.log('Success:', value);
+});
+```
+
+In this example, `Promise.withResolvers()` gives you full control over when and how the promise is resolved or rejected, without needing to define the executor function inline. This pattern is commonly used in event-driven programming, timeouts, or when integrating with non-promise-based APIs.
+
+## Error Handling with Promises
+
+Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
+
+- You can use `.catch()` to handle any errors or rejections that occur during the execution of Promises.
+
+```js
+myPromise
+  .then(result => console.log(result))
+  .catch(error => console.error(error)) // Handles the rejection
+  .finally(error => console.log('Promise completed')); // Runs regardless of promise resolution
+```
+
+- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
+
+```js
+async function performTask() {
+  try {
+    const result = await myPromise;
+    console.log(result);
+  } catch (error) {
+    console.error(error); // Handles any errors
+  } finally {
+    // This code is executed regardless of failure
+    console.log('performTask() completed');
+  }
+}
+
+performTask();
+```
+
+## Scheduling Tasks in the Event Loop
+
+In addition to Promises, Node.js provides several other mechanisms for scheduling tasks in the event loop.
+
+### **`queueMicrotask()`**
+
+`queueMicrotask()` is used to schedule a microtask, which is a lightweight task that runs after the currently executing script but before any other I/O events or timers. Microtasks include tasks like Promise resolutions and other asynchronous operations that are prioritized over regular tasks.
+
+```js
+queueMicrotask(() => {
+  console.log('Microtask is executed');
+});
+
+console.log('Synchronous task is executed');
+```
+
+In the above example, "Microtask is executed" will be logged after "Synchronous task is executed," but before any I/O operations like timers.
+
+### **`process.nextTick()`**
+
+`process.nextTick()` is used to schedule a callback to be executed immediately after the current operation completes. This is useful for situations where you want to ensure that a callback is executed as soon as possible, but still after the current execution context.
+
+```js
+process.nextTick(() => {
+  console.log('Next tick callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **`setImmediate()`**:
+
+`setImmediate()` is used to execute a callback after the current event loop cycle finishes and all I/O events have been processed. This means that `setImmediate()` callbacks run after any I/O callbacks, but before timers.
+
+```js
+setImmediate(() => {
+  console.log('Immediate callback');
+});
+
+console.log('Synchronous task executed');
+```
+
+### **When to Use Each**:
+
+- Use `queueMicrotask()` for tasks that need to run immediately after the current script and before any I/O or timer callbacks, typically for Promise resolutions.
+- Use `process.nextTick()` for tasks that should execute before any I/O events, often useful for deferring operations or handling errors synchronously.
+- Use `setImmediate()` for tasks that should run after I/O events but before timers.
+
+Because these tasks execute outside of the current synchronous flow, uncaught exceptions inside these callbacks won't be caught by surrounding `try/catch` blocks and may crash the application if not properly managed (e.g., by attaching `.catch()` to Promises or using global error handlers like `process.on('uncaughtException')`).
+
+In short, the execution order is as follows:
+
+1. **Synchronous code** (e.g., regular function calls and script code)
+2. **`process.nextTick()`** callbacks
+3. **Microtasks** (e.g., Promises, `queueMicrotask()`)
+   If a microtask queues another microtask, the new one is also executed before moving on.
+4. **Timers** (e.g., `setTimeout()`, `setInterval()`)
+5. **I/O callbacks** (e.g., network and file system operations)
+   Some operations, like `close` and `error` events, may use `process.nextTick()` internally and are executed in the next tick.
+6. **`setImmediate()`** callbacks
+
+`process.nextTick()` can execute at any stage in the execution order, as it is not bound by the event loop.
path: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
user: login: avivkeller
body: I realized we have another article on the event loop, so I've referenced it instead
created_at: 2025-04-12T20:52:17Z
author_association: MEMBER

PR comments:
user: login: vercel[bot]
created_at: 2025-04-12T00:15:22Z
body: [vc]: #TuB6QXFKq+lZ8KaOvw22yNVJul+tzsFg93EBjkMFSJg=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJub2RlanMtb3JnIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL29wZW5qcy9ub2RlanMtb3JnL0VhZFhXVXBTTW9mcWZYMXptMWNTRjFDZWNydGYiLCJwcmV2aWV3VXJsIjoibm9kZWpzLW9yZy1naXQtZmVhdC1sZWFybnByb21pc2VzLW9wZW5qcy52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IkRFUExPWUVEIiwicm9vdERpcmVjdG9yeSI6ImFwcHMvc2l0ZSJ9XX0=
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Updated (UTC) |
| :--- | :----- | :------ | :------ |
| **nodejs-org** | ✅ Ready ([Inspect](https://vercel.com/openjs/nodejs-org/EadXWUpSMofqfX1zm1cSF1Cecrtf)) | [Visit Preview](https://nodejs-org-git-feat-learnpromises-openjs.vercel.app) | Apr 12, 2025 8:55pm |


author_association: NONE
user: login: avivkeller
created_at: 2025-04-12T00:16:07Z
body: See https://nodejs-org-git-feat-learnpromises-openjs.vercel.app/en/learn/asynchronous-work/discover-promises-in-nodejs
author_association: MEMBER
user: login: avivkeller
created_at: 2025-04-12T13:47:17Z
body: @mcollina I've attempted to resolve your reviews in 81801200
author_association: MEMBER
user: login: github-actions[bot]
created_at: 2025-04-14T13:37:50Z
body: Lighthouse Results
URL | Performance | Accessibility | Best Practices | SEO | Report
| - | - | - | - | - | - |
[/en](https://nodejs-p8lnwf1tn-openjs.vercel.app/en) | 🟢 100 | 🟢 100 | 🟢 100 | 🟢 91 | [🔗](https://storage.googleapis.com/lighthouse-infrastructure.appspot.com/reports/1744637938160-14334.report.html)
[/en/about](https://nodejs-p8lnwf1tn-openjs.vercel.app/en/about) | 🟢 100 | 🟢 100 | 🟢 100 | 🟢 91 | [🔗](https://storage.googleapis.com/lighthouse-infrastructure.appspot.com/reports/1744637938546-26764.report.html)
[/en/about/previous-releases](https://nodejs-p8lnwf1tn-openjs.vercel.app/en/about/previous-releases) | 🟢 99 | 🟢 100 | 🟢 100 | 🟢 92 | [🔗](https://storage.googleapis.com/lighthouse-infrastructure.appspot.com/reports/1744637938876-63105.report.html)
[/en/download](https://nodejs-p8lnwf1tn-openjs.vercel.app/en/download) | 🟠 89 | 🟢 100 | 🟢 100 | 🟢 91 | [🔗](https://storage.googleapis.com/lighthouse-infrastructure.appspot.com/reports/1744637939175-18296.report.html)
[/en/blog](https://nodejs-p8lnwf1tn-openjs.vercel.app/en/blog) | 🟢 100 | 🟢 100 | 🟢 96 | 🟢 92 | [🔗](https://storage.googleapis.com/lighthouse-infrastructure.appspot.com/reports/1744637939431-39939.report.html)
<!-- thollander/actions-comment-pull-request "lighthouse_audit" -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-14T13:38:40Z
body: <!-- Jest Coverage Comment: tests -->
# Unit Test Coverage Report



| Title | Lines | Statements | Branches | Functions |
| --- | --- | --- | --- | --- |
| @node-core/ui-components | <a href="https://github.com/nodejs/nodejs.org/blob//README.md"><img alt="Coverage: 95%" src="https://img.shields.io/badge/Coverage-95%25-brightgreen.svg" /></a><br/> | 95.83% (161/168) | 77.86% (102/131) | 88.57% (31/35) |
| @nodejs/website | <a href="https://github.com/nodejs/nodejs.org/blob//README.md"><img alt="Coverage: 87%" src="https://img.shields.io/badge/Coverage-87%25-green.svg" /></a><br/> | 84.7% (493/582) | 76.03% (165/217) | 86.88% (106/122) |


| Title | Tests | Skipped | Failures | Errors | Time |
| --- | --- | --- | --- | --- | --- |
| @node-core/ui-components | 24 | 0 :zzz: | 0 :x: | 0 :fire: | 4.744s :stopwatch: |
| @nodejs/website | 156 | 0 :zzz: | 0 :x: | 0 :fire: | 6.603s :stopwatch: |

author_association: CONTRIBUTOR
user: login: avivkeller
created_at: 2025-04-17T14:38:54Z
body: bump @mcollina (Previously requested changes) @nodejs/nodejs-website (Required) for reviews.
author_association: MEMBER
user: login: avivkeller
created_at: 2025-04-18T11:51:44Z
body: It's been a while since any objections, so I'm merging this PR. Any changes can be requested in a follow up.
author_association: MEMBER