Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc: revise error.md introduction #48423

Merged
merged 1 commit into from Jun 15, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
89 changes: 28 additions & 61 deletions doc/api/errors.md
Expand Up @@ -46,15 +46,35 @@ try {
```

Any use of the JavaScript `throw` mechanism will raise an exception that
_must_ be handled using `try…catch` or the Node.js process will exit
immediately.
_must_ be handled or the Node.js process will exit immediately.

With few exceptions, _Synchronous_ APIs (any blocking method that does not
accept a `callback` function, such as [`fs.readFileSync`][]), will use `throw`
to report errors.
return a {Promise} nor accept a `callback` function, such as
[`fs.readFileSync`][]), will use `throw` to report errors.

Errors that occur within _Asynchronous APIs_ may be reported in multiple ways:

* Some asynchronous methods returns a {Promise}, you should always take into
account that it might be rejected. See [`--unhandled-rejections`][] flag for
how the process will react to an unhandled promise rejection.

<!-- eslint-disable no-useless-return -->

```js
const fs = require('fs/promises');

(async () => {
let data;
try {
data = await fs.readFile('a file that does not exist');
} catch (err) {
console.error('There was an error reading the file!', err);
return;
}
// Otherwise handle the data
})();
```

* Most asynchronous methods that accept a `callback` function will accept an
`Error` object passed as the first argument to that function. If that first
argument is not `null` and is an instance of `Error`, then an error occurred
Expand Down Expand Up @@ -104,9 +124,9 @@ pass or fail).

For _all_ [`EventEmitter`][] objects, if an `'error'` event handler is not
provided, the error will be thrown, causing the Node.js process to report an
uncaught exception and crash unless either: The [`domain`][domains] module is
used appropriately or a handler has been registered for the
[`'uncaughtException'`][] event.
uncaught exception and crash unless either: a handler has been registered for
the [`'uncaughtException'`][] event, or the deprecated [`node:domain`][domains]
module is used.

```js
const EventEmitter = require('node:events');
Expand All @@ -125,60 +145,6 @@ they are thrown _after_ the calling code has already exited.
Developers must refer to the documentation for each method to determine
exactly how errors raised by those methods are propagated.

### Error-first callbacks

<!--type=misc-->

Most asynchronous methods exposed by the Node.js core API follow an idiomatic
pattern referred to as an _error-first callback_. With this pattern, a callback
function is passed to the method as an argument. When the operation either
completes or an error is raised, the callback function is called with the
`Error` object (if any) passed as the first argument. If no error was raised,
the first argument will be passed as `null`.

```js
const fs = require('node:fs');

function errorFirstCallback(err, data) {
if (err) {
console.error('There was an error', err);
return;
}
console.log(data);
}

fs.readFile('/some/file/that/does-not-exist', errorFirstCallback);
fs.readFile('/some/file/that/does-exist', errorFirstCallback);
```

The JavaScript `try…catch` mechanism **cannot** be used to intercept errors
generated by asynchronous APIs. A common mistake for beginners is to try to
use `throw` inside an error-first callback:

```js
// THIS WILL NOT WORK:
const fs = require('node:fs');

try {
fs.readFile('/some/file/that/does-not-exist', (err, data) => {
// Mistaken assumption: throwing here...
if (err) {
throw err;
}
});
} catch (err) {
// This will not catch the throw!
console.error(err);
}
```

This will not work because the callback function passed to `fs.readFile()` is
called asynchronously. By the time the callback has been called, the
surrounding code, including the `try…catch` block, will have already exited.
Throwing an error inside the callback **can crash the Node.js process** in most
cases. If [domains][] are enabled, or a handler has been registered with
`process.on('uncaughtException')`, such errors can be intercepted.

## Class: `Error`

<!--type=class-->
Expand Down Expand Up @@ -3600,6 +3566,7 @@ The native call from `process.cpuUsage` could not be processed.
[`--disable-proto=throw`]: cli.md#--disable-protomode
[`--force-fips`]: cli.md#--force-fips
[`--no-addons`]: cli.md#--no-addons
[`--unhandled-rejections`]: cli.md#--unhandled-rejectionsmode
[`Class: assert.AssertionError`]: assert.md#class-assertassertionerror
[`ERR_INVALID_ARG_TYPE`]: #err_invalid_arg_type
[`ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST`]: #err_missing_message_port_in_transfer_list
Expand Down