Skip to content

Commit d39c1cf

Browse files
committed
doc: more use-cases for promise events
This adds an example of a semi-common promise pattern that could result in false-positive 'unhandledRejection' events, to help motivate why there is a dual 'rejectionHandled' event. I anticipate it being helpful to users who encounter 'unhandledRejection' events that do not stem from obvious typos such as the JSON.pasre example. Also cleans up the promise rejection tracking sample. By using a Set instead of array we can get O(1) deletion. And, fixed indentation and backtick usage there to align with the rest of the document.
1 parent 73b7e05 commit d39c1cf

File tree

1 file changed

+27
-7
lines changed

1 file changed

+27
-7
lines changed

doc/api/process.markdown

+27-7
Original file line numberDiff line numberDiff line change
@@ -159,40 +159,60 @@ event:
159159
return reportToUser(JSON.pasre(res)); // note the typo
160160
}); // no `.catch` or `.then`
161161

162+
Here is an example of a coding pattern that will also trigger
163+
`'unhandledRejection'`:
164+
165+
function SomeResource() {
166+
// Initially set the loaded status to a rejected promise
167+
this.loaded = Promise.reject(new Error('Resource not yet loaded!'));
168+
}
169+
170+
var resource = new SomeResource();
171+
// no .catch or .then on resource.loaded for at least a turn
172+
173+
To deal with cases like this, which you likely don't want to track as developer
174+
error in the same way as other `'unhandledRejection'` events, you can either
175+
attach a dummy `.catch(function() { })` handler to `resource.loaded`,
176+
preventing the `'unhandledRejection'` event from being emitted, or you can use
177+
the 'rejectionHandled' event.
178+
162179
## Event: 'rejectionHandled'
163180

164181
Emitted whenever a Promise was rejected and an error handler was attached to it
165182
(for example with `.catch()`) later than after an event loop turn. This event
166183
is emitted with the following arguments:
167184

168-
- `p` the promise that was previously emitted in an 'unhandledRejection'
185+
- `p` the promise that was previously emitted in an `'unhandledRejection'`
169186
event, but which has now gained a rejection handler.
170187

171188
There is no notion of a top level for a promise chain at which rejections can
172189
always be handled. Being inherently asynchronous in nature, a promise rejection
173190
can be be handled at a future point in time — possibly much later than the
174-
event loop turn it takes for the 'unhandledRejection' event to be emitted.
191+
event loop turn it takes for the `'unhandledRejection'` event to be emitted.
175192

176193
Another way of stating this is that, unlike in synchronous code where there is
177194
an ever-growing list of unhandled exceptions, with promises there is a
178195
growing-and-shrinking list of unhandled rejections. In synchronous code, the
179196
'uncaughtException' event tells you when the list of unhandled exceptions
180-
grows. And in asynchronous code, the 'unhandledRejection' event tells you
197+
grows. And in asynchronous code, the `'unhandledRejection'` event tells you
181198
when the list of unhandled rejections grows, while the 'rejectionHandled'
182199
event tells you when the list of unhandled rejections shrinks.
183200

184201
For example using the rejection detection hooks in order to keep a list of all
185202
the rejected promises at a given time:
186203

187-
var unhandledRejections = [];
204+
var unhandledRejections = new Set();
188205
process.on('unhandledRejection', function(reason, p) {
189-
unhandledRejections.push(p);
206+
unhandledRejections.add(p);
190207
});
191208
process.on('rejectionHandled', function(p) {
192-
var index = unhandledRejections.indexOf(p);
193-
unhandledRejections.splice(index, 1);
209+
unhandledRejections.delete(p);
194210
});
195211

212+
You could then record this list in some error log, either periodically or upon
213+
process exit. This would avoid the false positive seen in the above resource
214+
example.
215+
196216
## Signal Events
197217

198218
<!--type=event-->

0 commit comments

Comments
 (0)