• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html>
2<html lang="en">
3<head>
4  <meta charset="utf-8">
5  <meta name="viewport" content="width=device-width">
6  <meta name="nodejs.org:node-version" content="v18.18.2">
7  <title>Asynchronous context tracking | Node.js v18.18.2 Documentation</title>
8  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Lato:400,700,400italic&display=fallback">
9  <link rel="stylesheet" href="assets/style.css">
10  <link rel="stylesheet" href="assets/hljs.css">
11  <link rel="canonical" href="https://nodejs.org/api/async_context.html">
12  <script async defer src="assets/api.js" type="text/javascript"></script>
13  <style>@media(max-width:1080px){.with-73-chars>.js-flavor-selector{float:none;margin:0 0 1em auto;}}@media(max-width:686px){.with-58-chars>.js-flavor-selector{float:none;margin:0 0 1em auto;}}@media(max-width:1072px){.with-72-chars>.js-flavor-selector{float:none;margin:0 0 1em auto;}}@media(max-width:654px){.with-54-chars>.js-flavor-selector{float:none;margin:0 0 1em auto;}}@media(max-width:598px){.with-47-chars>.js-flavor-selector{float:none;margin:0 0 1em auto;}}</style>
14</head>
15<body class="alt apidoc" id="api-section-async_context">
16  <div id="content" class="clearfix">
17    <div id="column2" class="interior">
18      <div id="intro" class="interior">
19        <a href="/" title="Go back to the home page">
20          Node.js
21        </a>
22      </div>
23      <ul>
24<li><a href="documentation.html" class="nav-documentation">About this documentation</a></li>
25<li><a href="synopsis.html" class="nav-synopsis">Usage and example</a></li>
26</ul>
27<hr class="line">
28<ul>
29<li><a href="assert.html" class="nav-assert">Assertion testing</a></li>
30<li><a href="async_context.html" class="nav-async_context active">Asynchronous context tracking</a></li>
31<li><a href="async_hooks.html" class="nav-async_hooks">Async hooks</a></li>
32<li><a href="buffer.html" class="nav-buffer">Buffer</a></li>
33<li><a href="addons.html" class="nav-addons">C++ addons</a></li>
34<li><a href="n-api.html" class="nav-n-api">C/C++ addons with Node-API</a></li>
35<li><a href="embedding.html" class="nav-embedding">C++ embedder API</a></li>
36<li><a href="child_process.html" class="nav-child_process">Child processes</a></li>
37<li><a href="cluster.html" class="nav-cluster">Cluster</a></li>
38<li><a href="cli.html" class="nav-cli">Command-line options</a></li>
39<li><a href="console.html" class="nav-console">Console</a></li>
40<li><a href="corepack.html" class="nav-corepack">Corepack</a></li>
41<li><a href="crypto.html" class="nav-crypto">Crypto</a></li>
42<li><a href="debugger.html" class="nav-debugger">Debugger</a></li>
43<li><a href="deprecations.html" class="nav-deprecations">Deprecated APIs</a></li>
44<li><a href="diagnostics_channel.html" class="nav-diagnostics_channel">Diagnostics Channel</a></li>
45<li><a href="dns.html" class="nav-dns">DNS</a></li>
46<li><a href="domain.html" class="nav-domain">Domain</a></li>
47<li><a href="errors.html" class="nav-errors">Errors</a></li>
48<li><a href="events.html" class="nav-events">Events</a></li>
49<li><a href="fs.html" class="nav-fs">File system</a></li>
50<li><a href="globals.html" class="nav-globals">Globals</a></li>
51<li><a href="http.html" class="nav-http">HTTP</a></li>
52<li><a href="http2.html" class="nav-http2">HTTP/2</a></li>
53<li><a href="https.html" class="nav-https">HTTPS</a></li>
54<li><a href="inspector.html" class="nav-inspector">Inspector</a></li>
55<li><a href="intl.html" class="nav-intl">Internationalization</a></li>
56<li><a href="modules.html" class="nav-modules">Modules: CommonJS modules</a></li>
57<li><a href="esm.html" class="nav-esm">Modules: ECMAScript modules</a></li>
58<li><a href="module.html" class="nav-module">Modules: <code>node:module</code> API</a></li>
59<li><a href="packages.html" class="nav-packages">Modules: Packages</a></li>
60<li><a href="net.html" class="nav-net">Net</a></li>
61<li><a href="os.html" class="nav-os">OS</a></li>
62<li><a href="path.html" class="nav-path">Path</a></li>
63<li><a href="perf_hooks.html" class="nav-perf_hooks">Performance hooks</a></li>
64<li><a href="permissions.html" class="nav-permissions">Permissions</a></li>
65<li><a href="process.html" class="nav-process">Process</a></li>
66<li><a href="punycode.html" class="nav-punycode">Punycode</a></li>
67<li><a href="querystring.html" class="nav-querystring">Query strings</a></li>
68<li><a href="readline.html" class="nav-readline">Readline</a></li>
69<li><a href="repl.html" class="nav-repl">REPL</a></li>
70<li><a href="report.html" class="nav-report">Report</a></li>
71<li><a href="single-executable-applications.html" class="nav-single-executable-applications">Single executable applications</a></li>
72<li><a href="stream.html" class="nav-stream">Stream</a></li>
73<li><a href="string_decoder.html" class="nav-string_decoder">String decoder</a></li>
74<li><a href="test.html" class="nav-test">Test runner</a></li>
75<li><a href="timers.html" class="nav-timers">Timers</a></li>
76<li><a href="tls.html" class="nav-tls">TLS/SSL</a></li>
77<li><a href="tracing.html" class="nav-tracing">Trace events</a></li>
78<li><a href="tty.html" class="nav-tty">TTY</a></li>
79<li><a href="dgram.html" class="nav-dgram">UDP/datagram</a></li>
80<li><a href="url.html" class="nav-url">URL</a></li>
81<li><a href="util.html" class="nav-util">Utilities</a></li>
82<li><a href="v8.html" class="nav-v8">V8</a></li>
83<li><a href="vm.html" class="nav-vm">VM</a></li>
84<li><a href="wasi.html" class="nav-wasi">WASI</a></li>
85<li><a href="webcrypto.html" class="nav-webcrypto">Web Crypto API</a></li>
86<li><a href="webstreams.html" class="nav-webstreams">Web Streams API</a></li>
87<li><a href="worker_threads.html" class="nav-worker_threads">Worker threads</a></li>
88<li><a href="zlib.html" class="nav-zlib">Zlib</a></li>
89</ul>
90<hr class="line">
91<ul>
92<li><a href="https://github.com/nodejs/node" class="nav-https-github-com-nodejs-node">Code repository and issue tracker</a></li>
93</ul>
94    </div>
95
96    <div id="column1" data-id="async_context" class="interior">
97      <header class="header">
98        <div class="header-container">
99          <h1>Node.js v18.18.2 documentation</h1>
100          <button class="theme-toggle-btn" id="theme-toggle-btn" title="Toggle dark mode/light mode" aria-label="Toggle dark mode/light mode" hidden>
101            <svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" height="24" width="24">
102              <path fill="none" d="M0 0h24v24H0z" />
103              <path d="M11.1 12.08c-2.33-4.51-.5-8.48.53-10.07C6.27 2.2 1.98 6.59 1.98 12c0 .14.02.28.02.42.62-.27 1.29-.42 2-.42 1.66 0 3.18.83 4.1 2.15A4.01 4.01 0 0111 18c0 1.52-.87 2.83-2.12 3.51.98.32 2.03.5 3.11.5 3.5 0 6.58-1.8 8.37-4.52-2.36.23-6.98-.97-9.26-5.41z"/>
104              <path d="M7 16h-.18C6.4 14.84 5.3 14 4 14c-1.66 0-3 1.34-3 3s1.34 3 3 3h3c1.1 0 2-.9 2-2s-.9-2-2-2z"/>
105            </svg>
106            <svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" height="24" width="24">
107              <path d="M0 0h24v24H0z" fill="none" />
108              <path d="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"/>
109            </svg>
110          </button>
111        </div>
112        <div id="gtoc">
113          <ul>
114            <li class="pinned-header">Node.js v18.18.2</li>
115
116    <li class="picker-header">
117      <a href="#">
118        <span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
119        Table of contents
120      </a>
121
122      <div class="picker"><div class="toc"><ul>
123<li><span class="stability_2"><a href="#asynchronous-context-tracking">Asynchronous context tracking</a></span>
124<ul>
125<li><a href="#introduction">Introduction</a></li>
126<li><a href="#class-asynclocalstorage">Class: <code>AsyncLocalStorage</code></a>
127<ul>
128<li><a href="#new-asynclocalstorage"><code>new AsyncLocalStorage()</code></a></li>
129<li><span class="stability_1"><a href="#static-method-asynclocalstoragebindfn">Static method: <code>AsyncLocalStorage.bind(fn)</code></a></span></li>
130<li><span class="stability_1"><a href="#static-method-asynclocalstoragesnapshot">Static method: <code>AsyncLocalStorage.snapshot()</code></a></span></li>
131<li><span class="stability_1"><a href="#asynclocalstoragedisable"><code>asyncLocalStorage.disable()</code></a></span></li>
132<li><a href="#asynclocalstoragegetstore"><code>asyncLocalStorage.getStore()</code></a></li>
133<li><span class="stability_1"><a href="#asynclocalstorageenterwithstore"><code>asyncLocalStorage.enterWith(store)</code></a></span></li>
134<li><a href="#asynclocalstoragerunstore-callback-args"><code>asyncLocalStorage.run(store, callback[, ...args])</code></a></li>
135<li><span class="stability_1"><a href="#asynclocalstorageexitcallback-args"><code>asyncLocalStorage.exit(callback[, ...args])</code></a></span></li>
136<li><a href="#usage-with-asyncawait">Usage with <code>async/await</code></a></li>
137<li><a href="#troubleshooting-context-loss">Troubleshooting: Context loss</a></li>
138</ul>
139</li>
140<li><a href="#class-asyncresource">Class: <code>AsyncResource</code></a>
141<ul>
142<li><a href="#new-asyncresourcetype-options"><code>new AsyncResource(type[, options])</code></a></li>
143<li><a href="#static-method-asyncresourcebindfn-type-thisarg">Static method: <code>AsyncResource.bind(fn[, type[, thisArg]])</code></a></li>
144<li><a href="#asyncresourcebindfn-thisarg"><code>asyncResource.bind(fn[, thisArg])</code></a></li>
145<li><a href="#asyncresourceruninasyncscopefn-thisarg-args"><code>asyncResource.runInAsyncScope(fn[, thisArg, ...args])</code></a></li>
146<li><a href="#asyncresourceemitdestroy"><code>asyncResource.emitDestroy()</code></a></li>
147<li><a href="#asyncresourceasyncid"><code>asyncResource.asyncId()</code></a></li>
148<li><a href="#asyncresourcetriggerasyncid"><code>asyncResource.triggerAsyncId()</code></a></li>
149<li><a href="#using-asyncresource-for-a-worker-thread-pool">Using <code>AsyncResource</code> for a <code>Worker</code> thread pool</a></li>
150<li><a href="#integrating-asyncresource-with-eventemitter">Integrating <code>AsyncResource</code> with <code>EventEmitter</code></a></li>
151</ul>
152</li>
153</ul>
154</li>
155</ul></div></div>
156    </li>
157
158
159    <li class="picker-header">
160      <a href="#">
161        <span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
162        Index
163      </a>
164
165      <div class="picker"><ul>
166<li><a href="documentation.html" class="nav-documentation">About this documentation</a></li>
167<li><a href="synopsis.html" class="nav-synopsis">Usage and example</a></li>
168
169      <li>
170        <a href="index.html">Index</a>
171      </li>
172    </ul>
173
174<hr class="line">
175<ul>
176<li><a href="assert.html" class="nav-assert">Assertion testing</a></li>
177<li><a href="async_context.html" class="nav-async_context active">Asynchronous context tracking</a></li>
178<li><a href="async_hooks.html" class="nav-async_hooks">Async hooks</a></li>
179<li><a href="buffer.html" class="nav-buffer">Buffer</a></li>
180<li><a href="addons.html" class="nav-addons">C++ addons</a></li>
181<li><a href="n-api.html" class="nav-n-api">C/C++ addons with Node-API</a></li>
182<li><a href="embedding.html" class="nav-embedding">C++ embedder API</a></li>
183<li><a href="child_process.html" class="nav-child_process">Child processes</a></li>
184<li><a href="cluster.html" class="nav-cluster">Cluster</a></li>
185<li><a href="cli.html" class="nav-cli">Command-line options</a></li>
186<li><a href="console.html" class="nav-console">Console</a></li>
187<li><a href="corepack.html" class="nav-corepack">Corepack</a></li>
188<li><a href="crypto.html" class="nav-crypto">Crypto</a></li>
189<li><a href="debugger.html" class="nav-debugger">Debugger</a></li>
190<li><a href="deprecations.html" class="nav-deprecations">Deprecated APIs</a></li>
191<li><a href="diagnostics_channel.html" class="nav-diagnostics_channel">Diagnostics Channel</a></li>
192<li><a href="dns.html" class="nav-dns">DNS</a></li>
193<li><a href="domain.html" class="nav-domain">Domain</a></li>
194<li><a href="errors.html" class="nav-errors">Errors</a></li>
195<li><a href="events.html" class="nav-events">Events</a></li>
196<li><a href="fs.html" class="nav-fs">File system</a></li>
197<li><a href="globals.html" class="nav-globals">Globals</a></li>
198<li><a href="http.html" class="nav-http">HTTP</a></li>
199<li><a href="http2.html" class="nav-http2">HTTP/2</a></li>
200<li><a href="https.html" class="nav-https">HTTPS</a></li>
201<li><a href="inspector.html" class="nav-inspector">Inspector</a></li>
202<li><a href="intl.html" class="nav-intl">Internationalization</a></li>
203<li><a href="modules.html" class="nav-modules">Modules: CommonJS modules</a></li>
204<li><a href="esm.html" class="nav-esm">Modules: ECMAScript modules</a></li>
205<li><a href="module.html" class="nav-module">Modules: <code>node:module</code> API</a></li>
206<li><a href="packages.html" class="nav-packages">Modules: Packages</a></li>
207<li><a href="net.html" class="nav-net">Net</a></li>
208<li><a href="os.html" class="nav-os">OS</a></li>
209<li><a href="path.html" class="nav-path">Path</a></li>
210<li><a href="perf_hooks.html" class="nav-perf_hooks">Performance hooks</a></li>
211<li><a href="permissions.html" class="nav-permissions">Permissions</a></li>
212<li><a href="process.html" class="nav-process">Process</a></li>
213<li><a href="punycode.html" class="nav-punycode">Punycode</a></li>
214<li><a href="querystring.html" class="nav-querystring">Query strings</a></li>
215<li><a href="readline.html" class="nav-readline">Readline</a></li>
216<li><a href="repl.html" class="nav-repl">REPL</a></li>
217<li><a href="report.html" class="nav-report">Report</a></li>
218<li><a href="single-executable-applications.html" class="nav-single-executable-applications">Single executable applications</a></li>
219<li><a href="stream.html" class="nav-stream">Stream</a></li>
220<li><a href="string_decoder.html" class="nav-string_decoder">String decoder</a></li>
221<li><a href="test.html" class="nav-test">Test runner</a></li>
222<li><a href="timers.html" class="nav-timers">Timers</a></li>
223<li><a href="tls.html" class="nav-tls">TLS/SSL</a></li>
224<li><a href="tracing.html" class="nav-tracing">Trace events</a></li>
225<li><a href="tty.html" class="nav-tty">TTY</a></li>
226<li><a href="dgram.html" class="nav-dgram">UDP/datagram</a></li>
227<li><a href="url.html" class="nav-url">URL</a></li>
228<li><a href="util.html" class="nav-util">Utilities</a></li>
229<li><a href="v8.html" class="nav-v8">V8</a></li>
230<li><a href="vm.html" class="nav-vm">VM</a></li>
231<li><a href="wasi.html" class="nav-wasi">WASI</a></li>
232<li><a href="webcrypto.html" class="nav-webcrypto">Web Crypto API</a></li>
233<li><a href="webstreams.html" class="nav-webstreams">Web Streams API</a></li>
234<li><a href="worker_threads.html" class="nav-worker_threads">Worker threads</a></li>
235<li><a href="zlib.html" class="nav-zlib">Zlib</a></li>
236</ul>
237<hr class="line">
238<ul>
239<li><a href="https://github.com/nodejs/node" class="nav-https-github-com-nodejs-node">Code repository and issue tracker</a></li>
240</ul></div>
241    </li>
242
243
244    <li class="picker-header">
245      <a href="#">
246        <span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
247        Other versions
248      </a>
249      <div class="picker"><ol id="alt-docs"><li><a href="https://nodejs.org/docs/latest-v20.x/api/async_context.html">20.x</a></li>
250<li><a href="https://nodejs.org/docs/latest-v19.x/api/async_context.html">19.x</a></li>
251<li><a href="https://nodejs.org/docs/latest-v18.x/api/async_context.html">18.x <b>LTS</b></a></li>
252<li><a href="https://nodejs.org/docs/latest-v17.x/api/async_context.html">17.x</a></li>
253<li><a href="https://nodejs.org/docs/latest-v16.x/api/async_context.html">16.x</a></li></ol></div>
254    </li>
255
256            <li class="picker-header">
257              <a href="#">
258                <span class="collapsed-arrow">&#x25ba;</span><span class="expanded-arrow">&#x25bc;</span>
259                Options
260              </a>
261
262              <div class="picker">
263                <ul>
264                  <li>
265                    <a href="all.html">View on single page</a>
266                  </li>
267                  <li>
268                    <a href="async_context.json">View as JSON</a>
269                  </li>
270                  <li class="edit_on_github"><a href="https://github.com/nodejs/node/edit/main/doc/api/async_context.md">Edit on GitHub</a></li>
271                </ul>
272              </div>
273            </li>
274          </ul>
275        </div>
276        <hr>
277      </header>
278
279      <details id="toc" open><summary>Table of contents</summary><ul>
280<li><span class="stability_2"><a href="#asynchronous-context-tracking">Asynchronous context tracking</a></span>
281<ul>
282<li><a href="#introduction">Introduction</a></li>
283<li><a href="#class-asynclocalstorage">Class: <code>AsyncLocalStorage</code></a>
284<ul>
285<li><a href="#new-asynclocalstorage"><code>new AsyncLocalStorage()</code></a></li>
286<li><span class="stability_1"><a href="#static-method-asynclocalstoragebindfn">Static method: <code>AsyncLocalStorage.bind(fn)</code></a></span></li>
287<li><span class="stability_1"><a href="#static-method-asynclocalstoragesnapshot">Static method: <code>AsyncLocalStorage.snapshot()</code></a></span></li>
288<li><span class="stability_1"><a href="#asynclocalstoragedisable"><code>asyncLocalStorage.disable()</code></a></span></li>
289<li><a href="#asynclocalstoragegetstore"><code>asyncLocalStorage.getStore()</code></a></li>
290<li><span class="stability_1"><a href="#asynclocalstorageenterwithstore"><code>asyncLocalStorage.enterWith(store)</code></a></span></li>
291<li><a href="#asynclocalstoragerunstore-callback-args"><code>asyncLocalStorage.run(store, callback[, ...args])</code></a></li>
292<li><span class="stability_1"><a href="#asynclocalstorageexitcallback-args"><code>asyncLocalStorage.exit(callback[, ...args])</code></a></span></li>
293<li><a href="#usage-with-asyncawait">Usage with <code>async/await</code></a></li>
294<li><a href="#troubleshooting-context-loss">Troubleshooting: Context loss</a></li>
295</ul>
296</li>
297<li><a href="#class-asyncresource">Class: <code>AsyncResource</code></a>
298<ul>
299<li><a href="#new-asyncresourcetype-options"><code>new AsyncResource(type[, options])</code></a></li>
300<li><a href="#static-method-asyncresourcebindfn-type-thisarg">Static method: <code>AsyncResource.bind(fn[, type[, thisArg]])</code></a></li>
301<li><a href="#asyncresourcebindfn-thisarg"><code>asyncResource.bind(fn[, thisArg])</code></a></li>
302<li><a href="#asyncresourceruninasyncscopefn-thisarg-args"><code>asyncResource.runInAsyncScope(fn[, thisArg, ...args])</code></a></li>
303<li><a href="#asyncresourceemitdestroy"><code>asyncResource.emitDestroy()</code></a></li>
304<li><a href="#asyncresourceasyncid"><code>asyncResource.asyncId()</code></a></li>
305<li><a href="#asyncresourcetriggerasyncid"><code>asyncResource.triggerAsyncId()</code></a></li>
306<li><a href="#using-asyncresource-for-a-worker-thread-pool">Using <code>AsyncResource</code> for a <code>Worker</code> thread pool</a></li>
307<li><a href="#integrating-asyncresource-with-eventemitter">Integrating <code>AsyncResource</code> with <code>EventEmitter</code></a></li>
308</ul>
309</li>
310</ul>
311</li>
312</ul></details>
313
314      <div id="apicontent">
315        <h2>Asynchronous context tracking<span><a class="mark" href="#asynchronous-context-tracking" id="asynchronous-context-tracking">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asynchronous_context_tracking"></a></h2>
316
317<p></p><div class="api_stability api_stability_2"><a href="documentation.html#stability-index">Stability: 2</a> - Stable</div><p></p>
318<p><strong>Source Code:</strong> <a href="https://github.com/nodejs/node/blob/v18.18.2/lib/async_hooks.js">lib/async_hooks.js</a></p>
319<section><h3>Introduction<span><a class="mark" href="#introduction" id="introduction">#</a></span><a aria-hidden="true" class="legacy" id="async_context_introduction"></a></h3>
320<p>These classes are used to associate state and propagate it throughout
321callbacks and promise chains.
322They allow storing data throughout the lifetime of a web request
323or any other asynchronous duration. It is similar to thread-local storage
324in other languages.</p>
325<p>The <code>AsyncLocalStorage</code> and <code>AsyncResource</code> classes are part of the
326<code>node:async_hooks</code> module:</p>
327
328<pre class="with-73-chars"><input class="js-flavor-selector" type="checkbox" checked aria-label="Show modern ES modules syntax"><code class="language-js mjs"><span class="hljs-keyword">import</span> { <span class="hljs-title class_">AsyncLocalStorage</span>, <span class="hljs-title class_">AsyncResource</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:async_hooks'</span>;</code><code class="language-js cjs"><span class="hljs-keyword">const</span> { <span class="hljs-title class_">AsyncLocalStorage</span>, <span class="hljs-title class_">AsyncResource</span> } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:async_hooks'</span>);</code><button class="copy-button">copy</button></pre>
329</section><section><h3>Class: <code>AsyncLocalStorage</code><span><a class="mark" href="#class-asynclocalstorage" id="class-asynclocalstorage">#</a></span><a aria-hidden="true" class="legacy" id="async_context_class_asynclocalstorage"></a></h3>
330<div class="api_metadata">
331<details class="changelog"><summary>History</summary>
332<table>
333<tbody><tr><th>Version</th><th>Changes</th></tr>
334<tr><td>v16.4.0</td>
335<td><p>AsyncLocalStorage is now Stable. Previously, it had been Experimental.</p></td></tr>
336<tr><td>v13.10.0, v12.17.0</td>
337<td><p><span>Added in: v13.10.0, v12.17.0</span></p></td></tr>
338</tbody></table>
339</details>
340</div>
341<p>This class creates stores that stay coherent through asynchronous operations.</p>
342<p>While you can create your own implementation on top of the <code>node:async_hooks</code>
343module, <code>AsyncLocalStorage</code> should be preferred as it is a performant and memory
344safe implementation that involves significant optimizations that are non-obvious
345to implement.</p>
346<p>The following example uses <code>AsyncLocalStorage</code> to build a simple logger
347that assigns IDs to incoming HTTP requests and includes them in messages
348logged within each request.</p>
349
350<pre class="with-58-chars"><input class="js-flavor-selector" type="checkbox" checked aria-label="Show modern ES modules syntax"><code class="language-js mjs"><span class="hljs-keyword">import</span> http <span class="hljs-keyword">from</span> <span class="hljs-string">'node:http'</span>;
351<span class="hljs-keyword">import</span> { <span class="hljs-title class_">AsyncLocalStorage</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:async_hooks'</span>;
352
353<span class="hljs-keyword">const</span> asyncLocalStorage = <span class="hljs-keyword">new</span> <span class="hljs-title class_">AsyncLocalStorage</span>();
354
355<span class="hljs-keyword">function</span> <span class="hljs-title function_">logWithId</span>(<span class="hljs-params">msg</span>) {
356  <span class="hljs-keyword">const</span> id = asyncLocalStorage.<span class="hljs-title function_">getStore</span>();
357  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`<span class="hljs-subst">${id !== <span class="hljs-literal">undefined</span> ? id : <span class="hljs-string">'-'</span>}</span>:`</span>, msg);
358}
359
360<span class="hljs-keyword">let</span> idSeq = <span class="hljs-number">0</span>;
361http.<span class="hljs-title function_">createServer</span>(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> {
362  asyncLocalStorage.<span class="hljs-title function_">run</span>(idSeq++, <span class="hljs-function">() =></span> {
363    <span class="hljs-title function_">logWithId</span>(<span class="hljs-string">'start'</span>);
364    <span class="hljs-comment">// Imagine any chain of async operations here</span>
365    <span class="hljs-title function_">setImmediate</span>(<span class="hljs-function">() =></span> {
366      <span class="hljs-title function_">logWithId</span>(<span class="hljs-string">'finish'</span>);
367      res.<span class="hljs-title function_">end</span>();
368    });
369  });
370}).<span class="hljs-title function_">listen</span>(<span class="hljs-number">8080</span>);
371
372http.<span class="hljs-title function_">get</span>(<span class="hljs-string">'http://localhost:8080'</span>);
373http.<span class="hljs-title function_">get</span>(<span class="hljs-string">'http://localhost:8080'</span>);
374<span class="hljs-comment">// Prints:</span>
375<span class="hljs-comment">//   0: start</span>
376<span class="hljs-comment">//   1: start</span>
377<span class="hljs-comment">//   0: finish</span>
378<span class="hljs-comment">//   1: finish</span></code><code class="language-js cjs"><span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:http'</span>);
379<span class="hljs-keyword">const</span> { <span class="hljs-title class_">AsyncLocalStorage</span> } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:async_hooks'</span>);
380
381<span class="hljs-keyword">const</span> asyncLocalStorage = <span class="hljs-keyword">new</span> <span class="hljs-title class_">AsyncLocalStorage</span>();
382
383<span class="hljs-keyword">function</span> <span class="hljs-title function_">logWithId</span>(<span class="hljs-params">msg</span>) {
384  <span class="hljs-keyword">const</span> id = asyncLocalStorage.<span class="hljs-title function_">getStore</span>();
385  <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">`<span class="hljs-subst">${id !== <span class="hljs-literal">undefined</span> ? id : <span class="hljs-string">'-'</span>}</span>:`</span>, msg);
386}
387
388<span class="hljs-keyword">let</span> idSeq = <span class="hljs-number">0</span>;
389http.<span class="hljs-title function_">createServer</span>(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> {
390  asyncLocalStorage.<span class="hljs-title function_">run</span>(idSeq++, <span class="hljs-function">() =></span> {
391    <span class="hljs-title function_">logWithId</span>(<span class="hljs-string">'start'</span>);
392    <span class="hljs-comment">// Imagine any chain of async operations here</span>
393    <span class="hljs-title function_">setImmediate</span>(<span class="hljs-function">() =></span> {
394      <span class="hljs-title function_">logWithId</span>(<span class="hljs-string">'finish'</span>);
395      res.<span class="hljs-title function_">end</span>();
396    });
397  });
398}).<span class="hljs-title function_">listen</span>(<span class="hljs-number">8080</span>);
399
400http.<span class="hljs-title function_">get</span>(<span class="hljs-string">'http://localhost:8080'</span>);
401http.<span class="hljs-title function_">get</span>(<span class="hljs-string">'http://localhost:8080'</span>);
402<span class="hljs-comment">// Prints:</span>
403<span class="hljs-comment">//   0: start</span>
404<span class="hljs-comment">//   1: start</span>
405<span class="hljs-comment">//   0: finish</span>
406<span class="hljs-comment">//   1: finish</span></code><button class="copy-button">copy</button></pre>
407<p>Each instance of <code>AsyncLocalStorage</code> maintains an independent storage context.
408Multiple instances can safely exist simultaneously without risk of interfering
409with each other's data.</p>
410<h4><code>new AsyncLocalStorage()</code><span><a class="mark" href="#new-asynclocalstorage" id="new-asynclocalstorage">#</a></span><a aria-hidden="true" class="legacy" id="async_context_new_asynclocalstorage"></a></h4>
411<div class="api_metadata">
412<details class="changelog"><summary>History</summary>
413<table>
414<tbody><tr><th>Version</th><th>Changes</th></tr>
415<tr><td>v18.16.0</td>
416<td><p>Removed experimental onPropagate option.</p></td></tr>
417<tr><td>v18.13.0</td>
418<td><p>Add option onPropagate.</p></td></tr>
419<tr><td>v13.10.0, v12.17.0</td>
420<td><p><span>Added in: v13.10.0, v12.17.0</span></p></td></tr>
421</tbody></table>
422</details>
423</div>
424<p>Creates a new instance of <code>AsyncLocalStorage</code>. Store is only provided within a
425<code>run()</code> call or after an <code>enterWith()</code> call.</p>
426<h4>Static method: <code>AsyncLocalStorage.bind(fn)</code><span><a class="mark" href="#static-method-asynclocalstoragebindfn" id="static-method-asynclocalstoragebindfn">#</a></span><a aria-hidden="true" class="legacy" id="async_context_static_method_asynclocalstorage_bind_fn"></a></h4>
427<div class="api_metadata">
428<span>Added in: v18.16.0</span>
429</div>
430<p></p><div class="api_stability api_stability_1"><a href="documentation.html#stability-index">Stability: 1</a> - Experimental</div><p></p>
431<ul>
432<li><code>fn</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">&#x3C;Function></a> The function to bind to the current execution context.</li>
433<li>Returns: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">&#x3C;Function></a> A new function that calls <code>fn</code> within the captured
434execution context.</li>
435</ul>
436<p>Binds the given function to the current execution context.</p>
437<h4>Static method: <code>AsyncLocalStorage.snapshot()</code><span><a class="mark" href="#static-method-asynclocalstoragesnapshot" id="static-method-asynclocalstoragesnapshot">#</a></span><a aria-hidden="true" class="legacy" id="async_context_static_method_asynclocalstorage_snapshot"></a></h4>
438<div class="api_metadata">
439<span>Added in: v18.16.0</span>
440</div>
441<p></p><div class="api_stability api_stability_1"><a href="documentation.html#stability-index">Stability: 1</a> - Experimental</div><p></p>
442<ul>
443<li>Returns: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">&#x3C;Function></a> A new function with the signature
444<code>(fn: (...args) : R, ...args) : R</code>.</li>
445</ul>
446<p>Captures the current execution context and returns a function that accepts a
447function as an argument. Whenever the returned function is called, it
448calls the function passed to it within the captured context.</p>
449<pre><code class="language-js"><span class="hljs-keyword">const</span> asyncLocalStorage = <span class="hljs-keyword">new</span> <span class="hljs-title class_">AsyncLocalStorage</span>();
450<span class="hljs-keyword">const</span> runInAsyncScope = asyncLocalStorage.<span class="hljs-title function_">run</span>(<span class="hljs-number">123</span>, <span class="hljs-function">() =></span> <span class="hljs-title class_">AsyncLocalStorage</span>.<span class="hljs-title function_">snapshot</span>());
451<span class="hljs-keyword">const</span> result = asyncLocalStorage.<span class="hljs-title function_">run</span>(<span class="hljs-number">321</span>, <span class="hljs-function">() =></span> <span class="hljs-title function_">runInAsyncScope</span>(<span class="hljs-function">() =></span> asyncLocalStorage.<span class="hljs-title function_">getStore</span>()));
452<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(result);  <span class="hljs-comment">// returns 123</span></code> <button class="copy-button">copy</button></pre>
453<p>AsyncLocalStorage.snapshot() can replace the use of AsyncResource for simple
454async context tracking purposes, for example:</p>
455<pre><code class="language-js"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Foo</span> {
456  #runInAsyncScope = <span class="hljs-title class_">AsyncLocalStorage</span>.<span class="hljs-title function_">snapshot</span>();
457
458  <span class="hljs-title function_">get</span>(<span class="hljs-params"></span>) { <span class="hljs-keyword">return</span> <span class="hljs-variable language_">this</span>.#<span class="hljs-title function_">runInAsyncScope</span>(<span class="hljs-function">() =></span> asyncLocalStorage.<span class="hljs-title function_">getStore</span>()); }
459}
460
461<span class="hljs-keyword">const</span> foo = asyncLocalStorage.<span class="hljs-title function_">run</span>(<span class="hljs-number">123</span>, <span class="hljs-function">() =></span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Foo</span>());
462<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(asyncLocalStorage.<span class="hljs-title function_">run</span>(<span class="hljs-number">321</span>, <span class="hljs-function">() =></span> foo.<span class="hljs-title function_">get</span>())); <span class="hljs-comment">// returns 123</span></code> <button class="copy-button">copy</button></pre>
463<h4><code>asyncLocalStorage.disable()</code><span><a class="mark" href="#asynclocalstoragedisable" id="asynclocalstoragedisable">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asynclocalstorage_disable"></a></h4>
464<div class="api_metadata">
465<span>Added in: v13.10.0, v12.17.0</span>
466</div>
467<p></p><div class="api_stability api_stability_1"><a href="documentation.html#stability-index">Stability: 1</a> - Experimental</div><p></p>
468<p>Disables the instance of <code>AsyncLocalStorage</code>. All subsequent calls
469to <code>asyncLocalStorage.getStore()</code> will return <code>undefined</code> until
470<code>asyncLocalStorage.run()</code> or <code>asyncLocalStorage.enterWith()</code> is called again.</p>
471<p>When calling <code>asyncLocalStorage.disable()</code>, all current contexts linked to the
472instance will be exited.</p>
473<p>Calling <code>asyncLocalStorage.disable()</code> is required before the
474<code>asyncLocalStorage</code> can be garbage collected. This does not apply to stores
475provided by the <code>asyncLocalStorage</code>, as those objects are garbage collected
476along with the corresponding async resources.</p>
477<p>Use this method when the <code>asyncLocalStorage</code> is not in use anymore
478in the current process.</p>
479<h4><code>asyncLocalStorage.getStore()</code><span><a class="mark" href="#asynclocalstoragegetstore" id="asynclocalstoragegetstore">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asynclocalstorage_getstore"></a></h4>
480<div class="api_metadata">
481<span>Added in: v13.10.0, v12.17.0</span>
482</div>
483<ul>
484<li>Returns: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types" class="type">&#x3C;any></a></li>
485</ul>
486<p>Returns the current store.
487If called outside of an asynchronous context initialized by
488calling <code>asyncLocalStorage.run()</code> or <code>asyncLocalStorage.enterWith()</code>, it
489returns <code>undefined</code>.</p>
490<h4><code>asyncLocalStorage.enterWith(store)</code><span><a class="mark" href="#asynclocalstorageenterwithstore" id="asynclocalstorageenterwithstore">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asynclocalstorage_enterwith_store"></a></h4>
491<div class="api_metadata">
492<span>Added in: v13.11.0, v12.17.0</span>
493</div>
494<p></p><div class="api_stability api_stability_1"><a href="documentation.html#stability-index">Stability: 1</a> - Experimental</div><p></p>
495<ul>
496<li><code>store</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types" class="type">&#x3C;any></a></li>
497</ul>
498<p>Transitions into the context for the remainder of the current
499synchronous execution and then persists the store through any following
500asynchronous calls.</p>
501<p>Example:</p>
502<pre><code class="language-js"><span class="hljs-keyword">const</span> store = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span> };
503<span class="hljs-comment">// Replaces previous store with the given store object</span>
504asyncLocalStorage.<span class="hljs-title function_">enterWith</span>(store);
505asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns the store object</span>
506<span class="hljs-title function_">someAsyncOperation</span>(<span class="hljs-function">() =></span> {
507  asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns the same object</span>
508});</code> <button class="copy-button">copy</button></pre>
509<p>This transition will continue for the <em>entire</em> synchronous execution.
510This means that if, for example, the context is entered within an event
511handler subsequent event handlers will also run within that context unless
512specifically bound to another context with an <code>AsyncResource</code>. That is why
513<code>run()</code> should be preferred over <code>enterWith()</code> unless there are strong reasons
514to use the latter method.</p>
515<pre><code class="language-js"><span class="hljs-keyword">const</span> store = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span> };
516
517emitter.<span class="hljs-title function_">on</span>(<span class="hljs-string">'my-event'</span>, <span class="hljs-function">() =></span> {
518  asyncLocalStorage.<span class="hljs-title function_">enterWith</span>(store);
519});
520emitter.<span class="hljs-title function_">on</span>(<span class="hljs-string">'my-event'</span>, <span class="hljs-function">() =></span> {
521  asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns the same object</span>
522});
523
524asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns undefined</span>
525emitter.<span class="hljs-title function_">emit</span>(<span class="hljs-string">'my-event'</span>);
526asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns the same object</span></code> <button class="copy-button">copy</button></pre>
527<h4><code>asyncLocalStorage.run(store, callback[, ...args])</code><span><a class="mark" href="#asynclocalstoragerunstore-callback-args" id="asynclocalstoragerunstore-callback-args">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asynclocalstorage_run_store_callback_args"></a></h4>
528<div class="api_metadata">
529<span>Added in: v13.10.0, v12.17.0</span>
530</div>
531<ul>
532<li><code>store</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types" class="type">&#x3C;any></a></li>
533<li><code>callback</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">&#x3C;Function></a></li>
534<li><code>...args</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types" class="type">&#x3C;any></a></li>
535</ul>
536<p>Runs a function synchronously within a context and returns its
537return value. The store is not accessible outside of the callback function.
538The store is accessible to any asynchronous operations created within the
539callback.</p>
540<p>The optional <code>args</code> are passed to the callback function.</p>
541<p>If the callback function throws an error, the error is thrown by <code>run()</code> too.
542The stacktrace is not impacted by this call and the context is exited.</p>
543<p>Example:</p>
544<pre><code class="language-js"><span class="hljs-keyword">const</span> store = { <span class="hljs-attr">id</span>: <span class="hljs-number">2</span> };
545<span class="hljs-keyword">try</span> {
546  asyncLocalStorage.<span class="hljs-title function_">run</span>(store, <span class="hljs-function">() =></span> {
547    asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns the store object</span>
548    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =></span> {
549      asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns the store object</span>
550    }, <span class="hljs-number">200</span>);
551    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>();
552  });
553} <span class="hljs-keyword">catch</span> (e) {
554  asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns undefined</span>
555  <span class="hljs-comment">// The error will be caught here</span>
556}</code> <button class="copy-button">copy</button></pre>
557<h4><code>asyncLocalStorage.exit(callback[, ...args])</code><span><a class="mark" href="#asynclocalstorageexitcallback-args" id="asynclocalstorageexitcallback-args">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asynclocalstorage_exit_callback_args"></a></h4>
558<div class="api_metadata">
559<span>Added in: v13.10.0, v12.17.0</span>
560</div>
561<p></p><div class="api_stability api_stability_1"><a href="documentation.html#stability-index">Stability: 1</a> - Experimental</div><p></p>
562<ul>
563<li><code>callback</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">&#x3C;Function></a></li>
564<li><code>...args</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types" class="type">&#x3C;any></a></li>
565</ul>
566<p>Runs a function synchronously outside of a context and returns its
567return value. The store is not accessible within the callback function or
568the asynchronous operations created within the callback. Any <code>getStore()</code>
569call done within the callback function will always return <code>undefined</code>.</p>
570<p>The optional <code>args</code> are passed to the callback function.</p>
571<p>If the callback function throws an error, the error is thrown by <code>exit()</code> too.
572The stacktrace is not impacted by this call and the context is re-entered.</p>
573<p>Example:</p>
574<pre><code class="language-js"><span class="hljs-comment">// Within a call to run</span>
575<span class="hljs-keyword">try</span> {
576  asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns the store object or value</span>
577  asyncLocalStorage.<span class="hljs-title function_">exit</span>(<span class="hljs-function">() =></span> {
578    asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns undefined</span>
579    <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Error</span>();
580  });
581} <span class="hljs-keyword">catch</span> (e) {
582  asyncLocalStorage.<span class="hljs-title function_">getStore</span>(); <span class="hljs-comment">// Returns the same object or value</span>
583  <span class="hljs-comment">// The error will be caught here</span>
584}</code> <button class="copy-button">copy</button></pre>
585<h4>Usage with <code>async/await</code><span><a class="mark" href="#usage-with-asyncawait" id="usage-with-asyncawait">#</a></span><a aria-hidden="true" class="legacy" id="async_context_usage_with_async_await"></a></h4>
586<p>If, within an async function, only one <code>await</code> call is to run within a context,
587the following pattern should be used:</p>
588<pre><code class="language-js"><span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">fn</span>(<span class="hljs-params"></span>) {
589  <span class="hljs-keyword">await</span> asyncLocalStorage.<span class="hljs-title function_">run</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Map</span>(), <span class="hljs-function">() =></span> {
590    asyncLocalStorage.<span class="hljs-title function_">getStore</span>().<span class="hljs-title function_">set</span>(<span class="hljs-string">'key'</span>, value);
591    <span class="hljs-keyword">return</span> <span class="hljs-title function_">foo</span>(); <span class="hljs-comment">// The return value of foo will be awaited</span>
592  });
593}</code> <button class="copy-button">copy</button></pre>
594<p>In this example, the store is only available in the callback function and the
595functions called by <code>foo</code>. Outside of <code>run</code>, calling <code>getStore</code> will return
596<code>undefined</code>.</p>
597<h4>Troubleshooting: Context loss<span><a class="mark" href="#troubleshooting-context-loss" id="troubleshooting-context-loss">#</a></span><a aria-hidden="true" class="legacy" id="async_context_troubleshooting_context_loss"></a></h4>
598<p>In most cases, <code>AsyncLocalStorage</code> works without issues. In rare situations, the
599current store is lost in one of the asynchronous operations.</p>
600<p>If your code is callback-based, it is enough to promisify it with
601<a href="util.html#utilpromisifyoriginal"><code>util.promisify()</code></a> so it starts working with native promises.</p>
602<p>If you need to use a callback-based API or your code assumes
603a custom thenable implementation, use the <a href="#class-asyncresource"><code>AsyncResource</code></a> class
604to associate the asynchronous operation with the correct execution context.
605Find the function call responsible for the context loss by logging the content
606of <code>asyncLocalStorage.getStore()</code> after the calls you suspect are responsible
607for the loss. When the code logs <code>undefined</code>, the last callback called is
608probably responsible for the context loss.</p>
609</section><section><h3>Class: <code>AsyncResource</code><span><a class="mark" href="#class-asyncresource" id="class-asyncresource">#</a></span><a aria-hidden="true" class="legacy" id="async_context_class_asyncresource"></a></h3>
610<div class="api_metadata">
611<details class="changelog"><summary>History</summary>
612<table>
613<tbody><tr><th>Version</th><th>Changes</th></tr>
614<tr><td>v16.4.0</td>
615<td><p>AsyncResource is now Stable. Previously, it had been Experimental.</p></td></tr>
616</tbody></table>
617</details>
618</div>
619<p>The class <code>AsyncResource</code> is designed to be extended by the embedder's async
620resources. Using this, users can easily trigger the lifetime events of their
621own resources.</p>
622<p>The <code>init</code> hook will trigger when an <code>AsyncResource</code> is instantiated.</p>
623<p>The following is an overview of the <code>AsyncResource</code> API.</p>
624
625<pre class="with-72-chars"><input class="js-flavor-selector" type="checkbox" checked aria-label="Show modern ES modules syntax"><code class="language-js mjs"><span class="hljs-keyword">import</span> { <span class="hljs-title class_">AsyncResource</span>, executionAsyncId } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:async_hooks'</span>;
626
627<span class="hljs-comment">// AsyncResource() is meant to be extended. Instantiating a</span>
628<span class="hljs-comment">// new AsyncResource() also triggers init. If triggerAsyncId is omitted then</span>
629<span class="hljs-comment">// async_hook.executionAsyncId() is used.</span>
630<span class="hljs-keyword">const</span> asyncResource = <span class="hljs-keyword">new</span> <span class="hljs-title class_">AsyncResource</span>(
631  type, { <span class="hljs-attr">triggerAsyncId</span>: <span class="hljs-title function_">executionAsyncId</span>(), <span class="hljs-attr">requireManualDestroy</span>: <span class="hljs-literal">false</span> },
632);
633
634<span class="hljs-comment">// Run a function in the execution context of the resource. This will</span>
635<span class="hljs-comment">// * establish the context of the resource</span>
636<span class="hljs-comment">// * trigger the AsyncHooks before callbacks</span>
637<span class="hljs-comment">// * call the provided function `fn` with the supplied arguments</span>
638<span class="hljs-comment">// * trigger the AsyncHooks after callbacks</span>
639<span class="hljs-comment">// * restore the original execution context</span>
640asyncResource.<span class="hljs-title function_">runInAsyncScope</span>(fn, thisArg, ...args);
641
642<span class="hljs-comment">// Call AsyncHooks destroy callbacks.</span>
643asyncResource.<span class="hljs-title function_">emitDestroy</span>();
644
645<span class="hljs-comment">// Return the unique ID assigned to the AsyncResource instance.</span>
646asyncResource.<span class="hljs-title function_">asyncId</span>();
647
648<span class="hljs-comment">// Return the trigger ID for the AsyncResource instance.</span>
649asyncResource.<span class="hljs-title function_">triggerAsyncId</span>();</code><code class="language-js cjs"><span class="hljs-keyword">const</span> { <span class="hljs-title class_">AsyncResource</span>, executionAsyncId } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:async_hooks'</span>);
650
651<span class="hljs-comment">// AsyncResource() is meant to be extended. Instantiating a</span>
652<span class="hljs-comment">// new AsyncResource() also triggers init. If triggerAsyncId is omitted then</span>
653<span class="hljs-comment">// async_hook.executionAsyncId() is used.</span>
654<span class="hljs-keyword">const</span> asyncResource = <span class="hljs-keyword">new</span> <span class="hljs-title class_">AsyncResource</span>(
655  type, { <span class="hljs-attr">triggerAsyncId</span>: <span class="hljs-title function_">executionAsyncId</span>(), <span class="hljs-attr">requireManualDestroy</span>: <span class="hljs-literal">false</span> },
656);
657
658<span class="hljs-comment">// Run a function in the execution context of the resource. This will</span>
659<span class="hljs-comment">// * establish the context of the resource</span>
660<span class="hljs-comment">// * trigger the AsyncHooks before callbacks</span>
661<span class="hljs-comment">// * call the provided function `fn` with the supplied arguments</span>
662<span class="hljs-comment">// * trigger the AsyncHooks after callbacks</span>
663<span class="hljs-comment">// * restore the original execution context</span>
664asyncResource.<span class="hljs-title function_">runInAsyncScope</span>(fn, thisArg, ...args);
665
666<span class="hljs-comment">// Call AsyncHooks destroy callbacks.</span>
667asyncResource.<span class="hljs-title function_">emitDestroy</span>();
668
669<span class="hljs-comment">// Return the unique ID assigned to the AsyncResource instance.</span>
670asyncResource.<span class="hljs-title function_">asyncId</span>();
671
672<span class="hljs-comment">// Return the trigger ID for the AsyncResource instance.</span>
673asyncResource.<span class="hljs-title function_">triggerAsyncId</span>();</code><button class="copy-button">copy</button></pre>
674<h4><code>new AsyncResource(type[, options])</code><span><a class="mark" href="#new-asyncresourcetype-options" id="new-asyncresourcetype-options">#</a></span><a aria-hidden="true" class="legacy" id="async_context_new_asyncresource_type_options"></a></h4>
675<ul>
676<li><code>type</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&#x3C;string></a> The type of async event.</li>
677<li><code>options</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object" class="type">&#x3C;Object></a>
678<ul>
679<li><code>triggerAsyncId</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type" class="type">&#x3C;number></a> The ID of the execution context that created this
680async event. <strong>Default:</strong> <code>executionAsyncId()</code>.</li>
681<li><code>requireManualDestroy</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type" class="type">&#x3C;boolean></a> If set to <code>true</code>, disables <code>emitDestroy</code>
682when the object is garbage collected. This usually does not need to be set
683(even if <code>emitDestroy</code> is called manually), unless the resource's <code>asyncId</code>
684is retrieved and the sensitive API's <code>emitDestroy</code> is called with it.
685When set to <code>false</code>, the <code>emitDestroy</code> call on garbage collection
686will only take place if there is at least one active <code>destroy</code> hook.
687<strong>Default:</strong> <code>false</code>.</li>
688</ul>
689</li>
690</ul>
691<p>Example usage:</p>
692<pre><code class="language-js"><span class="hljs-keyword">class</span> <span class="hljs-title class_">DBQuery</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">AsyncResource</span> {
693  <span class="hljs-title function_">constructor</span>(<span class="hljs-params">db</span>) {
694    <span class="hljs-variable language_">super</span>(<span class="hljs-string">'DBQuery'</span>);
695    <span class="hljs-variable language_">this</span>.<span class="hljs-property">db</span> = db;
696  }
697
698  <span class="hljs-title function_">getInfo</span>(<span class="hljs-params">query, callback</span>) {
699    <span class="hljs-variable language_">this</span>.<span class="hljs-property">db</span>.<span class="hljs-title function_">get</span>(query, <span class="hljs-function">(<span class="hljs-params">err, data</span>) =></span> {
700      <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">runInAsyncScope</span>(callback, <span class="hljs-literal">null</span>, err, data);
701    });
702  }
703
704  <span class="hljs-title function_">close</span>(<span class="hljs-params"></span>) {
705    <span class="hljs-variable language_">this</span>.<span class="hljs-property">db</span> = <span class="hljs-literal">null</span>;
706    <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">emitDestroy</span>();
707  }
708}</code> <button class="copy-button">copy</button></pre>
709<h4>Static method: <code>AsyncResource.bind(fn[, type[, thisArg]])</code><span><a class="mark" href="#static-method-asyncresourcebindfn-type-thisarg" id="static-method-asyncresourcebindfn-type-thisarg">#</a></span><a aria-hidden="true" class="legacy" id="async_context_static_method_asyncresource_bind_fn_type_thisarg"></a></h4>
710<div class="api_metadata">
711<details class="changelog"><summary>History</summary>
712<table>
713<tbody><tr><th>Version</th><th>Changes</th></tr>
714<tr><td>v17.8.0</td>
715<td><p>Changed the default when <code>thisArg</code> is undefined to use <code>this</code> from the caller.</p></td></tr>
716<tr><td>v16.0.0</td>
717<td><p>Added optional thisArg.</p></td></tr>
718<tr><td>v14.8.0, v12.19.0</td>
719<td><p><span>Added in: v14.8.0, v12.19.0</span></p></td></tr>
720</tbody></table>
721</details>
722</div>
723<ul>
724<li><code>fn</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">&#x3C;Function></a> The function to bind to the current execution context.</li>
725<li><code>type</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type" class="type">&#x3C;string></a> An optional name to associate with the underlying
726<code>AsyncResource</code>.</li>
727<li><code>thisArg</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types" class="type">&#x3C;any></a></li>
728</ul>
729<p>Binds the given function to the current execution context.</p>
730<p>The returned function will have an <code>asyncResource</code> property referencing
731the <code>AsyncResource</code> to which the function is bound.</p>
732<h4><code>asyncResource.bind(fn[, thisArg])</code><span><a class="mark" href="#asyncresourcebindfn-thisarg" id="asyncresourcebindfn-thisarg">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asyncresource_bind_fn_thisarg"></a></h4>
733<div class="api_metadata">
734<details class="changelog"><summary>History</summary>
735<table>
736<tbody><tr><th>Version</th><th>Changes</th></tr>
737<tr><td>v17.8.0</td>
738<td><p>Changed the default when <code>thisArg</code> is undefined to use <code>this</code> from the caller.</p></td></tr>
739<tr><td>v16.0.0</td>
740<td><p>Added optional thisArg.</p></td></tr>
741<tr><td>v14.8.0, v12.19.0</td>
742<td><p><span>Added in: v14.8.0, v12.19.0</span></p></td></tr>
743</tbody></table>
744</details>
745</div>
746<ul>
747<li><code>fn</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">&#x3C;Function></a> The function to bind to the current <code>AsyncResource</code>.</li>
748<li><code>thisArg</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types" class="type">&#x3C;any></a></li>
749</ul>
750<p>Binds the given function to execute to this <code>AsyncResource</code>'s scope.</p>
751<p>The returned function will have an <code>asyncResource</code> property referencing
752the <code>AsyncResource</code> to which the function is bound.</p>
753<h4><code>asyncResource.runInAsyncScope(fn[, thisArg, ...args])</code><span><a class="mark" href="#asyncresourceruninasyncscopefn-thisarg-args" id="asyncresourceruninasyncscopefn-thisarg-args">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asyncresource_runinasyncscope_fn_thisarg_args"></a></h4>
754<div class="api_metadata">
755<span>Added in: v9.6.0</span>
756</div>
757<ul>
758<li><code>fn</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function" class="type">&#x3C;Function></a> The function to call in the execution context of this async
759resource.</li>
760<li><code>thisArg</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types" class="type">&#x3C;any></a> The receiver to be used for the function call.</li>
761<li><code>...args</code> <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types" class="type">&#x3C;any></a> Optional arguments to pass to the function.</li>
762</ul>
763<p>Call the provided function with the provided arguments in the execution context
764of the async resource. This will establish the context, trigger the AsyncHooks
765before callbacks, call the function, trigger the AsyncHooks after callbacks, and
766then restore the original execution context.</p>
767<h4><code>asyncResource.emitDestroy()</code><span><a class="mark" href="#asyncresourceemitdestroy" id="asyncresourceemitdestroy">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asyncresource_emitdestroy"></a></h4>
768<ul>
769<li>Returns: <a href="async_hooks.html#class-asyncresource" class="type">&#x3C;AsyncResource></a> A reference to <code>asyncResource</code>.</li>
770</ul>
771<p>Call all <code>destroy</code> hooks. This should only ever be called once. An error will
772be thrown if it is called more than once. This <strong>must</strong> be manually called. If
773the resource is left to be collected by the GC then the <code>destroy</code> hooks will
774never be called.</p>
775<h4><code>asyncResource.asyncId()</code><span><a class="mark" href="#asyncresourceasyncid" id="asyncresourceasyncid">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asyncresource_asyncid"></a></h4>
776<ul>
777<li>Returns: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type" class="type">&#x3C;number></a> The unique <code>asyncId</code> assigned to the resource.</li>
778</ul>
779<h4><code>asyncResource.triggerAsyncId()</code><span><a class="mark" href="#asyncresourcetriggerasyncid" id="asyncresourcetriggerasyncid">#</a></span><a aria-hidden="true" class="legacy" id="async_context_asyncresource_triggerasyncid"></a></h4>
780<ul>
781<li>Returns: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type" class="type">&#x3C;number></a> The same <code>triggerAsyncId</code> that is passed to the
782<code>AsyncResource</code> constructor.</li>
783</ul>
784<p><a id="async-resource-worker-pool"></a></p>
785<h4>Using <code>AsyncResource</code> for a <code>Worker</code> thread pool<span><a class="mark" href="#using-asyncresource-for-a-worker-thread-pool" id="using-asyncresource-for-a-worker-thread-pool">#</a></span><a aria-hidden="true" class="legacy" id="async_context_using_asyncresource_for_a_worker_thread_pool"></a></h4>
786<p>The following example shows how to use the <code>AsyncResource</code> class to properly
787provide async tracking for a <a href="worker_threads.html#class-worker"><code>Worker</code></a> pool. Other resource pools, such as
788database connection pools, can follow a similar model.</p>
789<p>Assuming that the task is adding two numbers, using a file named
790<code>task_processor.js</code> with the following content:</p>
791
792<pre class="with-54-chars"><input class="js-flavor-selector" type="checkbox" checked aria-label="Show modern ES modules syntax"><code class="language-js mjs"><span class="hljs-keyword">import</span> { parentPort } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:worker_threads'</span>;
793parentPort.<span class="hljs-title function_">on</span>(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">task</span>) =></span> {
794  parentPort.<span class="hljs-title function_">postMessage</span>(task.<span class="hljs-property">a</span> + task.<span class="hljs-property">b</span>);
795});</code><code class="language-js cjs"><span class="hljs-keyword">const</span> { parentPort } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:worker_threads'</span>);
796parentPort.<span class="hljs-title function_">on</span>(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">task</span>) =></span> {
797  parentPort.<span class="hljs-title function_">postMessage</span>(task.<span class="hljs-property">a</span> + task.<span class="hljs-property">b</span>);
798});</code><button class="copy-button">copy</button></pre>
799<p>a Worker pool around it could use the following structure:</p>
800
801<pre class="with-54-chars"><input class="js-flavor-selector" type="checkbox" checked aria-label="Show modern ES modules syntax"><code class="language-js mjs"><span class="hljs-keyword">import</span> { <span class="hljs-title class_">AsyncResource</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:async_hooks'</span>;
802<span class="hljs-keyword">import</span> { <span class="hljs-title class_">EventEmitter</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:events'</span>;
803<span class="hljs-keyword">import</span> path <span class="hljs-keyword">from</span> <span class="hljs-string">'node:path'</span>;
804<span class="hljs-keyword">import</span> { <span class="hljs-title class_">Worker</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:worker_threads'</span>;
805
806<span class="hljs-keyword">const</span> kTaskInfo = <span class="hljs-title class_">Symbol</span>(<span class="hljs-string">'kTaskInfo'</span>);
807<span class="hljs-keyword">const</span> kWorkerFreedEvent = <span class="hljs-title class_">Symbol</span>(<span class="hljs-string">'kWorkerFreedEvent'</span>);
808
809<span class="hljs-keyword">class</span> <span class="hljs-title class_">WorkerPoolTaskInfo</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">AsyncResource</span> {
810  <span class="hljs-title function_">constructor</span>(<span class="hljs-params">callback</span>) {
811    <span class="hljs-variable language_">super</span>(<span class="hljs-string">'WorkerPoolTaskInfo'</span>);
812    <span class="hljs-variable language_">this</span>.<span class="hljs-property">callback</span> = callback;
813  }
814
815  <span class="hljs-title function_">done</span>(<span class="hljs-params">err, result</span>) {
816    <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">runInAsyncScope</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">callback</span>, <span class="hljs-literal">null</span>, err, result);
817    <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">emitDestroy</span>();  <span class="hljs-comment">// `TaskInfo`s are used only once.</span>
818  }
819}
820
821<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">WorkerPool</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">EventEmitter</span> {
822  <span class="hljs-title function_">constructor</span>(<span class="hljs-params">numThreads</span>) {
823    <span class="hljs-variable language_">super</span>();
824    <span class="hljs-variable language_">this</span>.<span class="hljs-property">numThreads</span> = numThreads;
825    <span class="hljs-variable language_">this</span>.<span class="hljs-property">workers</span> = [];
826    <span class="hljs-variable language_">this</span>.<span class="hljs-property">freeWorkers</span> = [];
827    <span class="hljs-variable language_">this</span>.<span class="hljs-property">tasks</span> = [];
828
829    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &#x3C; numThreads; i++)
830      <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">addNewWorker</span>();
831
832    <span class="hljs-comment">// Any time the kWorkerFreedEvent is emitted, dispatch</span>
833    <span class="hljs-comment">// the next task pending in the queue, if any.</span>
834    <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">on</span>(kWorkerFreedEvent, <span class="hljs-function">() =></span> {
835      <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">tasks</span>.<span class="hljs-property">length</span> > <span class="hljs-number">0</span>) {
836        <span class="hljs-keyword">const</span> { task, callback } = <span class="hljs-variable language_">this</span>.<span class="hljs-property">tasks</span>.<span class="hljs-title function_">shift</span>();
837        <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">runTask</span>(task, callback);
838      }
839    });
840  }
841
842  <span class="hljs-title function_">addNewWorker</span>(<span class="hljs-params"></span>) {
843    <span class="hljs-keyword">const</span> worker = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Worker</span>(<span class="hljs-keyword">new</span> <span class="hljs-title function_">URL</span>(<span class="hljs-string">'task_processor.js'</span>, <span class="hljs-keyword">import</span>.<span class="hljs-property">meta</span>.<span class="hljs-property">url</span>));
844    worker.<span class="hljs-title function_">on</span>(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">result</span>) =></span> {
845      <span class="hljs-comment">// In case of success: Call the callback that was passed to `runTask`,</span>
846      <span class="hljs-comment">// remove the `TaskInfo` associated with the Worker, and mark it as free</span>
847      <span class="hljs-comment">// again.</span>
848      worker[kTaskInfo].<span class="hljs-title function_">done</span>(<span class="hljs-literal">null</span>, result);
849      worker[kTaskInfo] = <span class="hljs-literal">null</span>;
850      <span class="hljs-variable language_">this</span>.<span class="hljs-property">freeWorkers</span>.<span class="hljs-title function_">push</span>(worker);
851      <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">emit</span>(kWorkerFreedEvent);
852    });
853    worker.<span class="hljs-title function_">on</span>(<span class="hljs-string">'error'</span>, <span class="hljs-function">(<span class="hljs-params">err</span>) =></span> {
854      <span class="hljs-comment">// In case of an uncaught exception: Call the callback that was passed to</span>
855      <span class="hljs-comment">// `runTask` with the error.</span>
856      <span class="hljs-keyword">if</span> (worker[kTaskInfo])
857        worker[kTaskInfo].<span class="hljs-title function_">done</span>(err, <span class="hljs-literal">null</span>);
858      <span class="hljs-keyword">else</span>
859        <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">emit</span>(<span class="hljs-string">'error'</span>, err);
860      <span class="hljs-comment">// Remove the worker from the list and start a new Worker to replace the</span>
861      <span class="hljs-comment">// current one.</span>
862      <span class="hljs-variable language_">this</span>.<span class="hljs-property">workers</span>.<span class="hljs-title function_">splice</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">workers</span>.<span class="hljs-title function_">indexOf</span>(worker), <span class="hljs-number">1</span>);
863      <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">addNewWorker</span>();
864    });
865    <span class="hljs-variable language_">this</span>.<span class="hljs-property">workers</span>.<span class="hljs-title function_">push</span>(worker);
866    <span class="hljs-variable language_">this</span>.<span class="hljs-property">freeWorkers</span>.<span class="hljs-title function_">push</span>(worker);
867    <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">emit</span>(kWorkerFreedEvent);
868  }
869
870  <span class="hljs-title function_">runTask</span>(<span class="hljs-params">task, callback</span>) {
871    <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">freeWorkers</span>.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
872      <span class="hljs-comment">// No free threads, wait until a worker thread becomes free.</span>
873      <span class="hljs-variable language_">this</span>.<span class="hljs-property">tasks</span>.<span class="hljs-title function_">push</span>({ task, callback });
874      <span class="hljs-keyword">return</span>;
875    }
876
877    <span class="hljs-keyword">const</span> worker = <span class="hljs-variable language_">this</span>.<span class="hljs-property">freeWorkers</span>.<span class="hljs-title function_">pop</span>();
878    worker[kTaskInfo] = <span class="hljs-keyword">new</span> <span class="hljs-title class_">WorkerPoolTaskInfo</span>(callback);
879    worker.<span class="hljs-title function_">postMessage</span>(task);
880  }
881
882  <span class="hljs-title function_">close</span>(<span class="hljs-params"></span>) {
883    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> worker <span class="hljs-keyword">of</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">workers</span>) worker.<span class="hljs-title function_">terminate</span>();
884  }
885}</code><code class="language-js cjs"><span class="hljs-keyword">const</span> { <span class="hljs-title class_">AsyncResource</span> } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:async_hooks'</span>);
886<span class="hljs-keyword">const</span> { <span class="hljs-title class_">EventEmitter</span> } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:events'</span>);
887<span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:path'</span>);
888<span class="hljs-keyword">const</span> { <span class="hljs-title class_">Worker</span> } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:worker_threads'</span>);
889
890<span class="hljs-keyword">const</span> kTaskInfo = <span class="hljs-title class_">Symbol</span>(<span class="hljs-string">'kTaskInfo'</span>);
891<span class="hljs-keyword">const</span> kWorkerFreedEvent = <span class="hljs-title class_">Symbol</span>(<span class="hljs-string">'kWorkerFreedEvent'</span>);
892
893<span class="hljs-keyword">class</span> <span class="hljs-title class_">WorkerPoolTaskInfo</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">AsyncResource</span> {
894  <span class="hljs-title function_">constructor</span>(<span class="hljs-params">callback</span>) {
895    <span class="hljs-variable language_">super</span>(<span class="hljs-string">'WorkerPoolTaskInfo'</span>);
896    <span class="hljs-variable language_">this</span>.<span class="hljs-property">callback</span> = callback;
897  }
898
899  <span class="hljs-title function_">done</span>(<span class="hljs-params">err, result</span>) {
900    <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">runInAsyncScope</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">callback</span>, <span class="hljs-literal">null</span>, err, result);
901    <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">emitDestroy</span>();  <span class="hljs-comment">// `TaskInfo`s are used only once.</span>
902  }
903}
904
905<span class="hljs-keyword">class</span> <span class="hljs-title class_">WorkerPool</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_ inherited__">EventEmitter</span> {
906  <span class="hljs-title function_">constructor</span>(<span class="hljs-params">numThreads</span>) {
907    <span class="hljs-variable language_">super</span>();
908    <span class="hljs-variable language_">this</span>.<span class="hljs-property">numThreads</span> = numThreads;
909    <span class="hljs-variable language_">this</span>.<span class="hljs-property">workers</span> = [];
910    <span class="hljs-variable language_">this</span>.<span class="hljs-property">freeWorkers</span> = [];
911    <span class="hljs-variable language_">this</span>.<span class="hljs-property">tasks</span> = [];
912
913    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &#x3C; numThreads; i++)
914      <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">addNewWorker</span>();
915
916    <span class="hljs-comment">// Any time the kWorkerFreedEvent is emitted, dispatch</span>
917    <span class="hljs-comment">// the next task pending in the queue, if any.</span>
918    <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">on</span>(kWorkerFreedEvent, <span class="hljs-function">() =></span> {
919      <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">tasks</span>.<span class="hljs-property">length</span> > <span class="hljs-number">0</span>) {
920        <span class="hljs-keyword">const</span> { task, callback } = <span class="hljs-variable language_">this</span>.<span class="hljs-property">tasks</span>.<span class="hljs-title function_">shift</span>();
921        <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">runTask</span>(task, callback);
922      }
923    });
924  }
925
926  <span class="hljs-title function_">addNewWorker</span>(<span class="hljs-params"></span>) {
927    <span class="hljs-keyword">const</span> worker = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Worker</span>(path.<span class="hljs-title function_">resolve</span>(__dirname, <span class="hljs-string">'task_processor.js'</span>));
928    worker.<span class="hljs-title function_">on</span>(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">result</span>) =></span> {
929      <span class="hljs-comment">// In case of success: Call the callback that was passed to `runTask`,</span>
930      <span class="hljs-comment">// remove the `TaskInfo` associated with the Worker, and mark it as free</span>
931      <span class="hljs-comment">// again.</span>
932      worker[kTaskInfo].<span class="hljs-title function_">done</span>(<span class="hljs-literal">null</span>, result);
933      worker[kTaskInfo] = <span class="hljs-literal">null</span>;
934      <span class="hljs-variable language_">this</span>.<span class="hljs-property">freeWorkers</span>.<span class="hljs-title function_">push</span>(worker);
935      <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">emit</span>(kWorkerFreedEvent);
936    });
937    worker.<span class="hljs-title function_">on</span>(<span class="hljs-string">'error'</span>, <span class="hljs-function">(<span class="hljs-params">err</span>) =></span> {
938      <span class="hljs-comment">// In case of an uncaught exception: Call the callback that was passed to</span>
939      <span class="hljs-comment">// `runTask` with the error.</span>
940      <span class="hljs-keyword">if</span> (worker[kTaskInfo])
941        worker[kTaskInfo].<span class="hljs-title function_">done</span>(err, <span class="hljs-literal">null</span>);
942      <span class="hljs-keyword">else</span>
943        <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">emit</span>(<span class="hljs-string">'error'</span>, err);
944      <span class="hljs-comment">// Remove the worker from the list and start a new Worker to replace the</span>
945      <span class="hljs-comment">// current one.</span>
946      <span class="hljs-variable language_">this</span>.<span class="hljs-property">workers</span>.<span class="hljs-title function_">splice</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">workers</span>.<span class="hljs-title function_">indexOf</span>(worker), <span class="hljs-number">1</span>);
947      <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">addNewWorker</span>();
948    });
949    <span class="hljs-variable language_">this</span>.<span class="hljs-property">workers</span>.<span class="hljs-title function_">push</span>(worker);
950    <span class="hljs-variable language_">this</span>.<span class="hljs-property">freeWorkers</span>.<span class="hljs-title function_">push</span>(worker);
951    <span class="hljs-variable language_">this</span>.<span class="hljs-title function_">emit</span>(kWorkerFreedEvent);
952  }
953
954  <span class="hljs-title function_">runTask</span>(<span class="hljs-params">task, callback</span>) {
955    <span class="hljs-keyword">if</span> (<span class="hljs-variable language_">this</span>.<span class="hljs-property">freeWorkers</span>.<span class="hljs-property">length</span> === <span class="hljs-number">0</span>) {
956      <span class="hljs-comment">// No free threads, wait until a worker thread becomes free.</span>
957      <span class="hljs-variable language_">this</span>.<span class="hljs-property">tasks</span>.<span class="hljs-title function_">push</span>({ task, callback });
958      <span class="hljs-keyword">return</span>;
959    }
960
961    <span class="hljs-keyword">const</span> worker = <span class="hljs-variable language_">this</span>.<span class="hljs-property">freeWorkers</span>.<span class="hljs-title function_">pop</span>();
962    worker[kTaskInfo] = <span class="hljs-keyword">new</span> <span class="hljs-title class_">WorkerPoolTaskInfo</span>(callback);
963    worker.<span class="hljs-title function_">postMessage</span>(task);
964  }
965
966  <span class="hljs-title function_">close</span>(<span class="hljs-params"></span>) {
967    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> worker <span class="hljs-keyword">of</span> <span class="hljs-variable language_">this</span>.<span class="hljs-property">workers</span>) worker.<span class="hljs-title function_">terminate</span>();
968  }
969}
970
971<span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span> = <span class="hljs-title class_">WorkerPool</span>;</code><button class="copy-button">copy</button></pre>
972<p>Without the explicit tracking added by the <code>WorkerPoolTaskInfo</code> objects,
973it would appear that the callbacks are associated with the individual <code>Worker</code>
974objects. However, the creation of the <code>Worker</code>s is not associated with the
975creation of the tasks and does not provide information about when tasks
976were scheduled.</p>
977<p>This pool could be used as follows:</p>
978
979<pre class="with-47-chars"><input class="js-flavor-selector" type="checkbox" checked aria-label="Show modern ES modules syntax"><code class="language-js mjs"><span class="hljs-keyword">import</span> <span class="hljs-title class_">WorkerPool</span> <span class="hljs-keyword">from</span> <span class="hljs-string">'./worker_pool.js'</span>;
980<span class="hljs-keyword">import</span> os <span class="hljs-keyword">from</span> <span class="hljs-string">'node:os'</span>;
981
982<span class="hljs-keyword">const</span> pool = <span class="hljs-keyword">new</span> <span class="hljs-title class_">WorkerPool</span>(os.<span class="hljs-title function_">availableParallelism</span>());
983
984<span class="hljs-keyword">let</span> finished = <span class="hljs-number">0</span>;
985<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &#x3C; <span class="hljs-number">10</span>; i++) {
986  pool.<span class="hljs-title function_">runTask</span>({ <span class="hljs-attr">a</span>: <span class="hljs-number">42</span>, <span class="hljs-attr">b</span>: <span class="hljs-number">100</span> }, <span class="hljs-function">(<span class="hljs-params">err, result</span>) =></span> {
987    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(i, err, result);
988    <span class="hljs-keyword">if</span> (++finished === <span class="hljs-number">10</span>)
989      pool.<span class="hljs-title function_">close</span>();
990  });
991}</code><code class="language-js cjs"><span class="hljs-keyword">const</span> <span class="hljs-title class_">WorkerPool</span> = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./worker_pool.js'</span>);
992<span class="hljs-keyword">const</span> os = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:os'</span>);
993
994<span class="hljs-keyword">const</span> pool = <span class="hljs-keyword">new</span> <span class="hljs-title class_">WorkerPool</span>(os.<span class="hljs-title function_">availableParallelism</span>());
995
996<span class="hljs-keyword">let</span> finished = <span class="hljs-number">0</span>;
997<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &#x3C; <span class="hljs-number">10</span>; i++) {
998  pool.<span class="hljs-title function_">runTask</span>({ <span class="hljs-attr">a</span>: <span class="hljs-number">42</span>, <span class="hljs-attr">b</span>: <span class="hljs-number">100</span> }, <span class="hljs-function">(<span class="hljs-params">err, result</span>) =></span> {
999    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(i, err, result);
1000    <span class="hljs-keyword">if</span> (++finished === <span class="hljs-number">10</span>)
1001      pool.<span class="hljs-title function_">close</span>();
1002  });
1003}</code><button class="copy-button">copy</button></pre>
1004<h4>Integrating <code>AsyncResource</code> with <code>EventEmitter</code><span><a class="mark" href="#integrating-asyncresource-with-eventemitter" id="integrating-asyncresource-with-eventemitter">#</a></span><a aria-hidden="true" class="legacy" id="async_context_integrating_asyncresource_with_eventemitter"></a></h4>
1005<p>Event listeners triggered by an <a href="events.html#class-eventemitter"><code>EventEmitter</code></a> may be run in a different
1006execution context than the one that was active when <code>eventEmitter.on()</code> was
1007called.</p>
1008<p>The following example shows how to use the <code>AsyncResource</code> class to properly
1009associate an event listener with the correct execution context. The same
1010approach can be applied to a <a href="stream.html#stream"><code>Stream</code></a> or a similar event-driven class.</p>
1011
1012<pre class="with-72-chars"><input class="js-flavor-selector" type="checkbox" checked aria-label="Show modern ES modules syntax"><code class="language-js mjs"><span class="hljs-keyword">import</span> { createServer } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:http'</span>;
1013<span class="hljs-keyword">import</span> { <span class="hljs-title class_">AsyncResource</span>, executionAsyncId } <span class="hljs-keyword">from</span> <span class="hljs-string">'node:async_hooks'</span>;
1014
1015<span class="hljs-keyword">const</span> server = <span class="hljs-title function_">createServer</span>(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> {
1016  req.<span class="hljs-title function_">on</span>(<span class="hljs-string">'close'</span>, <span class="hljs-title class_">AsyncResource</span>.<span class="hljs-title function_">bind</span>(<span class="hljs-function">() =></span> {
1017    <span class="hljs-comment">// Execution context is bound to the current outer scope.</span>
1018  }));
1019  req.<span class="hljs-title function_">on</span>(<span class="hljs-string">'close'</span>, <span class="hljs-function">() =></span> {
1020    <span class="hljs-comment">// Execution context is bound to the scope that caused 'close' to emit.</span>
1021  });
1022  res.<span class="hljs-title function_">end</span>();
1023}).<span class="hljs-title function_">listen</span>(<span class="hljs-number">3000</span>);</code><code class="language-js cjs"><span class="hljs-keyword">const</span> { createServer } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:http'</span>);
1024<span class="hljs-keyword">const</span> { <span class="hljs-title class_">AsyncResource</span>, executionAsyncId } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:async_hooks'</span>);
1025
1026<span class="hljs-keyword">const</span> server = <span class="hljs-title function_">createServer</span>(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> {
1027  req.<span class="hljs-title function_">on</span>(<span class="hljs-string">'close'</span>, <span class="hljs-title class_">AsyncResource</span>.<span class="hljs-title function_">bind</span>(<span class="hljs-function">() =></span> {
1028    <span class="hljs-comment">// Execution context is bound to the current outer scope.</span>
1029  }));
1030  req.<span class="hljs-title function_">on</span>(<span class="hljs-string">'close'</span>, <span class="hljs-function">() =></span> {
1031    <span class="hljs-comment">// Execution context is bound to the scope that caused 'close' to emit.</span>
1032  });
1033  res.<span class="hljs-title function_">end</span>();
1034}).<span class="hljs-title function_">listen</span>(<span class="hljs-number">3000</span>);</code><button class="copy-button">copy</button></pre></section>
1035        <!-- API END -->
1036      </div>
1037    </div>
1038  </div>
1039</body>
1040</html>
1041