You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: apps/site/pages/en/learn/asynchronous-work/discover-promises-in-nodejs.md
+87-21Lines changed: 87 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,7 +6,7 @@ authors: avivkeller
6
6
7
7
# Discover Promises in Node.js
8
8
9
-
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.
9
+
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.
10
10
11
11
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."
12
12
@@ -18,11 +18,16 @@ A Promise can be in one of three states:
18
18
-**Fulfilled**: The operation completed successfully, and the Promise is now resolved with a value.
19
19
-**Rejected**: The operation failed, and the Promise is settled with a reason (usually an error).
20
20
21
-
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.
21
+
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.
22
+
23
+
Regardless of whether your dinner ends in joy or disappointment, once there's a final outcome, the Promise is considered **settled**.
22
24
23
25
## Basic Syntax of a Promise
24
26
25
-
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**.
27
+
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**.
28
+
29
+
If an error is thrown inside the executor function, the Promise will be rejected with that error.
30
+
The return value of the executor function is ignored: only `resolve` or `reject` should be used to settle the Promise.
26
31
27
32
```js
28
33
constmyPromise=newPromise((resolve, reject) => {
@@ -41,12 +46,13 @@ In the above example:
41
46
- If the `success` condition is `true`, the Promise is fulfilled and the value `'Operation was successful!'` is passed to the `resolve` function.
42
47
- If the `success` condition is `false`, the Promise is rejected and the error `'Something went wrong.'` is passed to the `reject` function.
43
48
44
-
## Handling Promises with `.then()`and `.catch()`
49
+
## Handling Promises with `.then()`, `.catch()`, and `.finally()`
45
50
46
-
Once a Promise is created, you can handle the outcome by using the `.then()`and `.catch()` methods.
51
+
Once a Promise is created, you can handle the outcome by using the `.then()`, `.catch()`, and `.finally()` methods.
47
52
48
53
-`.then()` is used to handle a fulfilled Promise and access its result.
49
54
-`.catch()` is used to handle a rejected Promise and catch any errors that may occur.
55
+
-`.finally()` is used to handle a settled Promise, regardless of whether the Promise resolved or rejected.
50
56
51
57
```js
52
58
constmyPromise=newPromise((resolve, reject) => {
@@ -65,6 +71,9 @@ myPromise
65
71
})
66
72
.catch(error=> {
67
73
console.error(error); // This will run if the Promise is rejected
74
+
})
75
+
.finally(() => {
76
+
console.log('The promise has completed'); // This will run when the Promise is settled
68
77
});
69
78
```
70
79
@@ -75,13 +84,12 @@ One of the great features of Promises is that they allow you to chain multiple a
returndelay(1000).then(() =>'Second task completed'); // Return a second Promise
85
93
})
86
94
.then(result=> {
87
95
console.log(result); // 'Second task completed'
@@ -96,7 +104,7 @@ promise1
96
104
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.
97
105
98
106
-`async` is used to define a function that returns a Promise.
99
-
-`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.
107
+
-`await` is used inside an `async` function to pause execution until a Promise settles.
100
108
101
109
```js
102
110
asyncfunctionperformTasks() {
@@ -114,7 +122,33 @@ async function performTasks() {
114
122
performTasks();
115
123
```
116
124
117
-
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.
125
+
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.
126
+
127
+
Essentially, the code above will execute the same as if the user wrote:
128
+
129
+
```js
130
+
promise1
131
+
.then(function (result1) {
132
+
console.log(result1);
133
+
return promise2;
134
+
})
135
+
.then(function (result2) {
136
+
console.log(result2);
137
+
})
138
+
.catch(function (error) {
139
+
console.log(error);
140
+
});
141
+
```
142
+
143
+
### Top-Level Await
144
+
145
+
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.
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.
120
154
@@ -149,9 +183,7 @@ JavaScript's `Promise` global provides several powerful methods that help manage
149
183
150
184
### **`Promise.all()`**:
151
185
152
-
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.
153
-
154
-
`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.
186
+
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.
@@ -186,7 +218,7 @@ Unlike `Promise.all()`, `Promise.allSettled()` does not short-circuit on failure
186
218
187
219
### **`Promise.race()`**:
188
220
189
-
This method resolves or rejects as soon as the first Promise settles, whether it resolves or rejects.
221
+
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.
`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.
267
+
268
+
This can be particularly useful for starting promise chains in a consistent way, especially when working with code that might throw errors synchronously.
269
+
270
+
```js
271
+
functionmightThrow() {
272
+
if (Math.random() >0.5) {
273
+
thrownewError('Oops, something went wrong!');
274
+
}
275
+
return'Success!';
276
+
}
277
+
278
+
Promise.try(mightThrow)
279
+
.then(result=> {
280
+
console.log('Result:', result);
281
+
})
282
+
.catch(err=> {
283
+
console.error('Caught error:', err.message);
284
+
});
285
+
```
286
+
287
+
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.
288
+
231
289
## Error Handling with Promises
232
290
233
291
Handling errors in Promises ensures your application behaves correctly in case of unexpected situations.
@@ -237,7 +295,8 @@ Handling errors in Promises ensures your application behaves correctly in case o
237
295
```js
238
296
myPromise
239
297
.then(result=>console.log(result))
240
-
.catch(error=>console.error(error)); // Handles the rejection
298
+
.catch(error=>console.error(error)) // Handles the rejection
299
+
.finally(error=>console.log('Promise completed')); // Runs regardless of promise resolution
241
300
```
242
301
243
302
- Alternatively, when using `async/await`, you can use a `try/catch` block to catch and handle errors.
@@ -278,7 +337,7 @@ In the above example, "Microtask is executed" will be logged after "Synchronous
278
337
279
338
### **`process.nextTick()`**
280
339
281
-
`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.
340
+
`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.
`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.
352
+
`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.
- Use `process.nextTick()` for tasks that should execute before any I/O events, often useful for deferring operations or handling errors synchronously.
307
366
- Use `setImmediate()` for tasks that should run after I/O events but before timers.
308
367
368
+
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')`).
369
+
309
370
In short, the execution order is as follows:
310
371
311
372
1.**Synchronous code** (e.g., regular function calls and script code)
`process.nextTick()` can execute at any stage in the execution order, as it is not bound by the event loop.
382
+
383
+
Note that this order, and the `process.nextTick()` functionality, is specific to Node.js, and other runtimes may handle different events at different times.
0 commit comments