Skip to content

Commit cf75a17

Browse files
domenicrvagg
authored andcommitted
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 Map instead of array we can get O(1) deletion and actually record the errors. And, fixed indentation and backtick usage there to align with the rest of the document. Reviewed-By: Stephan Belanger <[email protected]> Reviewed-By: Petka Antonov <[email protected]> Reviewed-By: James M Snell <[email protected]> PR-URL: #3438
1 parent 1b75d4b commit cf75a17

File tree

1 file changed

+32
-9
lines changed

1 file changed

+32
-9
lines changed

doc/api/process.markdown

+32-9
Original file line numberDiff line numberDiff line change
@@ -159,40 +159,63 @@ 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+
In cases like this, you may not want to track the rejection as a developer
174+
error like you would for other `'unhandledRejection'` events. To address
175+
this, you can either attach a dummy `.catch(function() { })` handler to
176+
`resource.loaded`, preventing the `'unhandledRejection'` event from being
177+
emitted, or you can use the `'rejectionHandled'` event. Below is an
178+
explanation of how to do that.
179+
162180
## Event: 'rejectionHandled'
163181

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

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

171189
There is no notion of a top level for a promise chain at which rejections can
172190
always be handled. Being inherently asynchronous in nature, a promise rejection
173191
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.
192+
event loop turn it takes for the `'unhandledRejection'` event to be emitted.
175193

176194
Another way of stating this is that, unlike in synchronous code where there is
177195
an ever-growing list of unhandled exceptions, with promises there is a
178196
growing-and-shrinking list of unhandled rejections. In synchronous code, the
179197
'uncaughtException' event tells you when the list of unhandled exceptions
180-
grows. And in asynchronous code, the 'unhandledRejection' event tells you
198+
grows. And in asynchronous code, the `'unhandledRejection'` event tells you
181199
when the list of unhandled rejections grows, while the 'rejectionHandled'
182200
event tells you when the list of unhandled rejections shrinks.
183201

184-
For example using the rejection detection hooks in order to keep a list of all
185-
the rejected promises at a given time:
202+
For example using the rejection detection hooks in order to keep a map of all
203+
the rejected promise reasons at a given time:
186204

187-
var unhandledRejections = [];
205+
var unhandledRejections = new Map();
188206
process.on('unhandledRejection', function(reason, p) {
189-
unhandledRejections.push(p);
207+
unhandledRejections.set(p, reason);
190208
});
191209
process.on('rejectionHandled', function(p) {
192-
var index = unhandledRejections.indexOf(p);
193-
unhandledRejections.splice(index, 1);
210+
unhandledRejections.delete(p);
194211
});
195212

213+
This map will grow and shrink over time, reflecting rejections that start
214+
unhandled and then become handled. You could record the errors in some error
215+
log, either periodically (probably best for long-running programs, allowing
216+
you to clear the map, which in the case of a very buggy program could grow
217+
indefinitely) or upon process exit (more convenient for scripts).
218+
196219
## Signal Events
197220

198221
<!--type=event-->

0 commit comments

Comments
 (0)