doc: add esm examples to node:util

PR-URL: https://github.com/nodejs/node/pull/56793
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This commit is contained in:
Alfredo González 2025-02-25 18:51:05 -03:00 committed by GitHub
parent 9840ca3348
commit c05f4baf32
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -10,7 +10,11 @@ The `node:util` module supports the needs of Node.js internal APIs. Many of the
utilities are useful for application and module developers as well. To access
it:
```js
```mjs
import util from 'node:util';
```
```cjs
const util = require('node:util');
```
@ -29,13 +33,27 @@ an `(err, value) => ...` callback as the last argument. In the callback, the
first argument will be the rejection reason (or `null` if the `Promise`
resolved), and the second argument will be the resolved value.
```js
const util = require('node:util');
```mjs
import { callbackify } from 'node:util';
async function fn() {
return 'hello world';
}
const callbackFunction = util.callbackify(fn);
const callbackFunction = callbackify(fn);
callbackFunction((err, ret) => {
if (err) throw err;
console.log(ret);
});
```
```cjs
const { callbackify } = require('node:util');
async function fn() {
return 'hello world';
}
const callbackFunction = callbackify(fn);
callbackFunction((err, ret) => {
if (err) throw err;
@ -89,11 +107,18 @@ environment variable. If the `section` name appears within the value of that
environment variable, then the returned function operates similar to
[`console.error()`][]. If not, then the returned function is a no-op.
```js
const util = require('node:util');
const debuglog = util.debuglog('foo');
```mjs
import { debuglog } from 'node:util';
const log = debuglog('foo');
debuglog('hello from foo [%d]', 123);
log('hello from foo [%d]', 123);
```
```cjs
const { debuglog } = require('node:util');
const log = debuglog('foo');
log('hello from foo [%d]', 123);
```
If this program is run with `NODE_DEBUG=foo` in the environment, then
@ -108,11 +133,18 @@ environment variable set, then it will not print anything.
The `section` supports wildcard also:
```js
const util = require('node:util');
const debuglog = util.debuglog('foo-bar');
```mjs
import { debuglog } from 'node:util';
const log = debuglog('foo');
debuglog('hi there, it\'s foo-bar [%d]', 2333);
log('hi there, it\'s foo-bar [%d]', 2333);
```
```cjs
const { debuglog } = require('node:util');
const log = debuglog('foo');
log('hi there, it\'s foo-bar [%d]', 2333);
```
if it is run with `NODE_DEBUG=foo*` in the environment, then it will output
@ -129,12 +161,21 @@ The optional `callback` argument can be used to replace the logging function
with a different function that doesn't have any initialization or
unnecessary wrapping.
```js
const util = require('node:util');
let debuglog = util.debuglog('internals', (debug) => {
```mjs
import { debuglog } from 'node:util';
let log = debuglog('internals', (debug) => {
// Replace with a logging function that optimizes out
// testing if the section is enabled
debuglog = debug;
log = debug;
});
```
```cjs
const { debuglog } = require('node:util');
let log = debuglog('internals', (debug) => {
// Replace with a logging function that optimizes out
// testing if the section is enabled
log = debug;
});
```
@ -152,9 +193,17 @@ If the `section` name appears within the value of that environment variable,
then the returned value will be `true`. If not, then the returned value will be
`false`.
```js
const util = require('node:util');
const enabled = util.debuglog('foo').enabled;
```mjs
import { debuglog } from 'node:util';
const enabled = debuglog('foo').enabled;
if (enabled) {
console.log('hello from foo [%d]', 123);
}
```
```cjs
const { debuglog } = require('node:util');
const enabled = debuglog('foo').enabled;
if (enabled) {
console.log('hello from foo [%d]', 123);
}
@ -196,10 +245,18 @@ changes:
The `util.deprecate()` method wraps `fn` (which may be a function or class) in
such a way that it is marked as deprecated.
```js
const util = require('node:util');
```mjs
import { deprecate } from 'node:util';
exports.obsoleteFunction = util.deprecate(() => {
export const obsoleteFunction = deprecate(() => {
// Do something here.
}, 'obsoleteFunction() is deprecated. Use newShinyFunction() instead.');
```
```cjs
const { deprecate } = require('node:util');
exports.obsoleteFunction = deprecate(() => {
// Do something here.
}, 'obsoleteFunction() is deprecated. Use newShinyFunction() instead.');
```
@ -213,11 +270,40 @@ emitting a warning.
If the same optional `code` is supplied in multiple calls to `util.deprecate()`,
the warning will be emitted only once for that `code`.
```js
const util = require('node:util');
```mjs
import { deprecate } from 'node:util';
const fn1 = util.deprecate(someFunction, someMessage, 'DEP0001');
const fn2 = util.deprecate(someOtherFunction, someOtherMessage, 'DEP0001');
const fn1 = deprecate(
() => 'a value',
'deprecation message',
'DEP0001',
);
const fn2 = deprecate(
() => 'a different value',
'other dep message',
'DEP0001',
);
fn1(); // Emits a deprecation warning with code DEP0001
fn2(); // Does not emit a deprecation warning because it has the same code
```
```cjs
const { deprecate } = require('node:util');
const fn1 = deprecate(
function() {
return 'a value';
},
'deprecation message',
'DEP0001',
);
const fn2 = deprecate(
function() {
return 'a different value';
},
'other dep message',
'DEP0001',
);
fn1(); // Emits a deprecation warning with code DEP0001
fn2(); // Does not emit a deprecation warning because it has the same code
```
@ -404,11 +490,11 @@ changes:
Returns an array of call site objects containing the stack of
the caller function.
```js
const util = require('node:util');
```mjs
import { getCallSites } from 'node:util';
function exampleFunction() {
const callSites = util.getCallSites();
const callSites = getCallSites();
console.log('Call Sites:');
callSites.forEach((callSite, index) => {
@ -416,7 +502,44 @@ function exampleFunction() {
console.log(`Function Name: ${callSite.functionName}`);
console.log(`Script Name: ${callSite.scriptName}`);
console.log(`Line Number: ${callSite.lineNumber}`);
console.log(`Column Number: ${callSite.columnNumber}`);
console.log(`Column Number: ${callSite.column}`);
});
// CallSite 1:
// Function Name: exampleFunction
// Script Name: /home/example.js
// Line Number: 5
// Column Number: 26
// CallSite 2:
// Function Name: anotherFunction
// Script Name: /home/example.js
// Line Number: 22
// Column Number: 3
// ...
}
// A function to simulate another stack layer
function anotherFunction() {
exampleFunction();
}
anotherFunction();
```
```cjs
const { getCallSites } = require('node:util');
function exampleFunction() {
const callSites = getCallSites();
console.log('Call Sites:');
callSites.forEach((callSite, index) => {
console.log(`CallSite ${index + 1}:`);
console.log(`Function Name: ${callSite.functionName}`);
console.log(`Script Name: ${callSite.scriptName}`);
console.log(`Line Number: ${callSite.lineNumber}`);
console.log(`Column Number: ${callSite.column}`);
});
// CallSite 1:
// Function Name: exampleFunction
@ -447,13 +570,31 @@ When the `--enable-source-maps` flag is enabled, for example when using `--exper
`sourceMap` will be true by default.
```ts
import util from 'node:util';
import { getCallSites } from 'node:util';
interface Foo {
foo: string;
}
const callSites = util.getCallSites({ sourceMap: true });
const callSites = getCallSites({ sourceMap: true });
// With sourceMap:
// Function Name: ''
// Script Name: example.js
// Line Number: 7
// Column Number: 26
// Without sourceMap:
// Function Name: ''
// Script Name: example.js
// Line Number: 2
// Column Number: 26
```
```cjs
const { getCallSites } = require('node:util');
const callSites = getCallSites({ sourceMap: true });
// With sourceMap:
// Function Name: ''
@ -587,7 +728,24 @@ stream.write('It works!'); // Received data: "It works!"
ES6 example using `class` and `extends`:
```js
```mjs
import EventEmitter from 'node:events';
class MyStream extends EventEmitter {
write(data) {
this.emit('data', data);
}
}
const stream = new MyStream();
stream.on('data', (data) => {
console.log(`Received data: "${data}"`);
});
stream.write('With ES6');
```
```cjs
const EventEmitter = require('node:events');
class MyStream extends EventEmitter {
@ -770,7 +928,23 @@ util.inspect(baz); // '[foo] {}'
Circular references point to their anchor by using a reference index:
```js
```mjs
import { inspect } from 'node:util';
const obj = {};
obj.a = [obj];
obj.b = {};
obj.b.inner = obj.b;
obj.b.obj = obj;
console.log(inspect(obj));
// <ref *1> {
// a: [ [Circular *1] ],
// b: <ref *2> { inner: [Circular *2], obj: [Circular *1] }
// }
```
```cjs
const { inspect } = require('node:util');
const obj = {};
@ -788,7 +962,13 @@ console.log(inspect(obj));
The following example inspects all properties of the `util` object:
```js
```mjs
import util from 'node:util';
console.log(util.inspect(util, { showHidden: true, depth: null }));
```
```cjs
const util = require('node:util');
console.log(util.inspect(util, { showHidden: true, depth: null }));
@ -796,8 +976,8 @@ console.log(util.inspect(util, { showHidden: true, depth: null }));
The following example highlights the effect of the `compact` option:
```js
const util = require('node:util');
```mjs
import { inspect } from 'node:util';
const o = {
a: [1, 2, [[
@ -807,7 +987,7 @@ const o = {
'foo']], 4],
b: new Map([['za', 1], ['zb', 'test']]),
};
console.log(util.inspect(o, { compact: true, depth: 5, breakLength: 80 }));
console.log(inspect(o, { compact: true, depth: 5, breakLength: 80 }));
// { a:
// [ 1,
@ -819,7 +999,57 @@ console.log(util.inspect(o, { compact: true, depth: 5, breakLength: 80 }));
// b: Map(2) { 'za' => 1, 'zb' => 'test' } }
// Setting `compact` to false or an integer creates more reader friendly output.
console.log(util.inspect(o, { compact: false, depth: 5, breakLength: 80 }));
console.log(inspect(o, { compact: false, depth: 5, breakLength: 80 }));
// {
// a: [
// 1,
// 2,
// [
// [
// 'Lorem ipsum dolor sit amet,\n' +
// 'consectetur adipiscing elit, sed do eiusmod \n' +
// 'tempor incididunt ut labore et dolore magna aliqua.',
// 'test',
// 'foo'
// ]
// ],
// 4
// ],
// b: Map(2) {
// 'za' => 1,
// 'zb' => 'test'
// }
// }
// Setting `breakLength` to e.g. 150 will print the "Lorem ipsum" text in a
// single line.
```
```cjs
const { inspect } = require('node:util');
const o = {
a: [1, 2, [[
'Lorem ipsum dolor sit amet,\nconsectetur adipiscing elit, sed do ' +
'eiusmod \ntempor incididunt ut labore et dolore magna aliqua.',
'test',
'foo']], 4],
b: new Map([['za', 1], ['zb', 'test']]),
};
console.log(inspect(o, { compact: true, depth: 5, breakLength: 80 }));
// { a:
// [ 1,
// 2,
// [ [ 'Lorem ipsum dolor sit amet,\nconsectetur [...]', // A long line
// 'test',
// 'foo' ] ],
// 4 ],
// b: Map(2) { 'za' => 1, 'zb' => 'test' } }
// Setting `compact` to false or an integer creates more reader friendly output.
console.log(inspect(o, { compact: false, depth: 5, breakLength: 80 }));
// {
// a: [
@ -852,7 +1082,18 @@ guarantee which entries are displayed. That means retrieving the same
{WeakSet} entries twice may result in different output. Furthermore, entries
with no remaining strong references may be garbage collected at any time.
```js
```mjs
import { inspect } from 'node:util';
const obj = { a: 1 };
const obj2 = { b: 2 };
const weakSet = new WeakSet([obj, obj2]);
console.log(inspect(weakSet, { showHidden: true }));
// WeakSet { { a: 1 }, { b: 2 } }
```
```cjs
const { inspect } = require('node:util');
const obj = { a: 1 };
@ -866,7 +1107,32 @@ console.log(inspect(weakSet, { showHidden: true }));
The `sorted` option ensures that an object's property insertion order does not
impact the result of `util.inspect()`.
```js
```mjs
import { inspect } from 'node:util';
import assert from 'node:assert';
const o1 = {
b: [2, 3, 1],
a: '`a` comes before `b`',
c: new Set([2, 3, 1]),
};
console.log(inspect(o1, { sorted: true }));
// { a: '`a` comes before `b`', b: [ 2, 3, 1 ], c: Set(3) { 1, 2, 3 } }
console.log(inspect(o1, { sorted: (a, b) => b.localeCompare(a) }));
// { c: Set(3) { 3, 2, 1 }, b: [ 2, 3, 1 ], a: '`a` comes before `b`' }
const o2 = {
c: new Set([2, 1, 3]),
a: '`a` comes before `b`',
b: [2, 3, 1],
};
assert.strict.equal(
inspect(o1, { sorted: true }),
inspect(o2, { sorted: true }),
);
```
```cjs
const { inspect } = require('node:util');
const assert = require('node:assert');
@ -894,13 +1160,31 @@ assert.strict.equal(
The `numericSeparator` option adds an underscore every three digits to all
numbers.
```js
```mjs
import { inspect } from 'node:util';
const thousand = 1000;
const million = 1000000;
const bigNumber = 123456789n;
const bigDecimal = 1234.12345;
console.log(inspect(thousand, { numericSeparator: true }));
// 1_000
console.log(inspect(million, { numericSeparator: true }));
// 1_000_000
console.log(inspect(bigNumber, { numericSeparator: true }));
// 123_456_789n
console.log(inspect(bigDecimal, { numericSeparator: true }));
// 1_234.123_45
```
```cjs
const { inspect } = require('node:util');
const thousand = 1_000;
const million = 1_000_000;
const bigNumber = 123_456_789n;
const bigDecimal = 1_234.123_45;
const thousand = 1000;
const million = 1000000;
const bigNumber = 123456789n;
const bigDecimal = 1234.12345;
console.log(inspect(thousand, { numericSeparator: true }));
// 1_000
@ -1026,15 +1310,15 @@ Objects may also define their own
which `util.inspect()` will invoke and use the result of when inspecting
the object.
```js
const util = require('node:util');
```mjs
import { inspect } from 'node:util';
class Box {
constructor(value) {
this.value = value;
}
[util.inspect.custom](depth, options, inspect) {
[inspect.custom](depth, options, inspect) {
if (depth < 0) {
return options.stylize('[Box]', 'special');
}
@ -1053,24 +1337,67 @@ class Box {
const box = new Box(true);
util.inspect(box);
// Returns: "Box< true >"
console.log(inspect(box));
// "Box< true >"
```
```cjs
const { inspect } = require('node:util');
class Box {
constructor(value) {
this.value = value;
}
[inspect.custom](depth, options, inspect) {
if (depth < 0) {
return options.stylize('[Box]', 'special');
}
const newOptions = Object.assign({}, options, {
depth: options.depth === null ? null : options.depth - 1,
});
// Five space padding because that's the size of "Box< ".
const padding = ' '.repeat(5);
const inner = inspect(this.value, newOptions)
.replace(/\n/g, `\n${padding}`);
return `${options.stylize('Box', 'special')}< ${inner} >`;
}
}
const box = new Box(true);
console.log(inspect(box));
// "Box< true >"
```
Custom `[util.inspect.custom](depth, opts, inspect)` functions typically return
a string but may return a value of any type that will be formatted accordingly
by `util.inspect()`.
```js
const util = require('node:util');
```mjs
import { inspect } from 'node:util';
const obj = { foo: 'this will not show up in the inspect() output' };
obj[util.inspect.custom] = (depth) => {
obj[inspect.custom] = (depth) => {
return { bar: 'baz' };
};
util.inspect(obj);
// Returns: "{ bar: 'baz' }"
console.log(inspect(obj));
// "{ bar: 'baz' }"
```
```cjs
const { inspect } = require('node:util');
const obj = { foo: 'this will not show up in the inspect() output' };
obj[inspect.custom] = (depth) => {
return { bar: 'baz' };
};
console.log(inspect(obj));
// "{ bar: 'baz' }"
```
### `util.inspect.custom`
@ -1130,12 +1457,21 @@ The `defaultOptions` value allows customization of the default options used by
object containing one or more valid [`util.inspect()`][] options. Setting
option properties directly is also supported.
```js
const util = require('node:util');
const arr = Array(101).fill(0);
```mjs
import { inspect } from 'node:util';
const arr = Array(156).fill(0);
console.log(arr); // Logs the truncated array
util.inspect.defaultOptions.maxArrayLength = null;
inspect.defaultOptions.maxArrayLength = null;
console.log(arr); // logs the full array
```
```cjs
const { inspect } = require('node:util');
const arr = Array(156).fill(0);
console.log(arr); // Logs the truncated array
inspect.defaultOptions.maxArrayLength = null;
console.log(arr); // logs the full array
```
@ -1777,12 +2113,24 @@ Takes a function following the common error-first callback style, i.e. taking
an `(err, value) => ...` callback as the last argument, and returns a version
that returns promises.
```js
const util = require('node:util');
const fs = require('node:fs');
```mjs
import { promisify } from 'node:util';
import { stat } from 'node:fs';
const stat = util.promisify(fs.stat);
stat('.').then((stats) => {
const promisifiedStat = promisify(stat);
promisifiedStat('.').then((stats) => {
// Do something with `stats`
}).catch((error) => {
// Handle the error.
});
```
```cjs
const { promisify } = require('node:util');
const { stat } = require('node:fs');
const promisifiedStat = promisify(stat);
promisifiedStat('.').then((stats) => {
// Do something with `stats`
}).catch((error) => {
// Handle the error.
@ -1791,14 +2139,28 @@ stat('.').then((stats) => {
Or, equivalently using `async function`s:
```js
const util = require('node:util');
const fs = require('node:fs');
```mjs
import { promisify } from 'node:util';
import { stat } from 'node:fs';
const stat = util.promisify(fs.stat);
const promisifiedStat = promisify(stat);
async function callStat() {
const stats = await stat('.');
const stats = await promisifiedStat('.');
console.log(`This directory is owned by ${stats.uid}`);
}
callStat();
```
```cjs
const { promisify } = require('node:util');
const { stat } = require('node:fs');
const promisifiedStat = promisify(stat);
async function callStat() {
const stats = await promisifiedStat('.');
console.log(`This directory is owned by ${stats.uid}`);
}
@ -1817,8 +2179,8 @@ callback as its last argument.
Using `promisify()` on class methods or other methods that use `this` may not
work as expected unless handled specially:
```js
const util = require('node:util');
```mjs
import { promisify } from 'node:util';
class Foo {
constructor() {
@ -1832,8 +2194,33 @@ class Foo {
const foo = new Foo();
const naiveBar = util.promisify(foo.bar);
// TypeError: Cannot read property 'a' of undefined
const naiveBar = promisify(foo.bar);
// TypeError: Cannot read properties of undefined (reading 'a')
// naiveBar().then(a => console.log(a));
naiveBar.call(foo).then((a) => console.log(a)); // '42'
const bindBar = naiveBar.bind(foo);
bindBar().then((a) => console.log(a)); // '42'
```
```cjs
const { promisify } = require('node:util');
class Foo {
constructor() {
this.a = 42;
}
bar(callback) {
callback(null, this.a);
}
}
const foo = new Foo();
const naiveBar = promisify(foo.bar);
// TypeError: Cannot read properties of undefined (reading 'a')
// naiveBar().then(a => console.log(a));
naiveBar.call(foo).then((a) => console.log(a)); // '42'
@ -1847,19 +2234,35 @@ bindBar().then((a) => console.log(a)); // '42'
Using the `util.promisify.custom` symbol one can override the return value of
[`util.promisify()`][]:
```js
const util = require('node:util');
```mjs
import { promisify } from 'node:util';
function doSomething(foo, callback) {
// ...
}
doSomething[util.promisify.custom] = (foo) => {
doSomething[promisify.custom] = (foo) => {
return getPromiseSomehow();
};
const promisified = util.promisify(doSomething);
console.log(promisified === doSomething[util.promisify.custom]);
const promisified = promisify(doSomething);
console.log(promisified === doSomething[promisify.custom]);
// prints 'true'
```
```cjs
const { promisify } = require('node:util');
function doSomething(foo, callback) {
// ...
}
doSomething[promisify.custom] = (foo) => {
return getPromiseSomehow();
};
const promisified = promisify(doSomething);
console.log(promisified === doSomething[promisify.custom]);
// prints 'true'
```
@ -2604,12 +3007,24 @@ DECLARE_NAPI_PROPERTY("myNapi", MyNapi)
...
```
```js
const native = require('napi_addon.node');
```mjs
import native from 'napi_addon.node';
import { types } from 'node:util';
const data = native.myNapi();
util.types.isExternal(data); // returns true
util.types.isExternal(0); // returns false
util.types.isExternal(new String('foo')); // returns false
types.isExternal(data); // returns true
types.isExternal(0); // returns false
types.isExternal(new String('foo')); // returns false
```
```cjs
const native = require('napi_addon.node');
const { types } = require('node:util');
const data = native.myNapi();
types.isExternal(data); // returns true
types.isExternal(0); // returns false
types.isExternal(new String('foo')); // returns false
```
For further information on `napi_create_external`, refer to
@ -2833,11 +3248,23 @@ returning `true` for that value. `isNativeError()` returns `true` for errors
which come from a different [realm][] while `instanceof Error` returns `false`
for these errors:
```js
const vm = require('node:vm');
const context = vm.createContext({});
const myError = vm.runInContext('new Error()', context);
console.log(util.types.isNativeError(myError)); // true
```mjs
import { createContext, runInContext } from 'node:vm';
import { types } from 'node:util';
const context = createContext({});
const myError = runInContext('new Error()', context);
console.log(types.isNativeError(myError)); // true
console.log(myError instanceof Error); // false
```
```cjs
const { createContext, runInContext } = require('node:vm');
const { types } = require('node:util');
const context = createContext({});
const myError = runInContext('new Error()', context);
console.log(types.isNativeError(myError)); // true
console.log(myError instanceof Error); // false
```