Skip to content

Commit

Permalink
doc: revise error.md introduction
Browse files Browse the repository at this point in the history
PR-URL: #48423
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Mestery <mestery@protonmail.com>
  • Loading branch information
aduh95 authored and ruyadorno committed Sep 12, 2023
1 parent 7575d8b commit 3cf3fb9
Showing 1 changed file with 28 additions and 61 deletions.
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 @@ -3576,6 +3542,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

0 comments on commit 3cf3fb9

Please sign in to comment.