From 3cf3fb9479f5ef21cefff9dc9f692c8b73230fb4 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Fri, 16 Jun 2023 01:24:53 +0200 Subject: [PATCH] doc: revise `error.md` introduction PR-URL: https://github.com/nodejs/node/pull/48423 Reviewed-By: Luigi Pinca Reviewed-By: Mestery --- doc/api/errors.md | 89 +++++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 61 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index bbad33b87583cf..9c88b7d7d4de0f 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -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. + + + + ```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 @@ -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'); @@ -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 - - - -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` @@ -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