File tree Expand file tree Collapse file tree 4 files changed +111
-0
lines changed
lib/internal/async_local_storage Expand file tree Collapse file tree 4 files changed +111
-0
lines changed Original file line number Diff line number Diff line change @@ -347,6 +347,43 @@ try {
347347}
348348```
349349
350+ ### ` asyncLocalStorage.use(store) `
351+
352+ <!-- YAML
353+ added: REPLACEME
354+ -->
355+
356+ * ` store ` {any}
357+ * Returns: {Disposable} A disposable object.
358+
359+ Transitions into the given context, and transitions back into the previous
360+ context when the returned disposable object is disposed. The store is
361+ accessible to any asynchronous operations created before disposal.
362+
363+ Example:
364+
365+ ``` js
366+ const store1 = { id: 1 };
367+ const store2 = { id: 2 };
368+
369+ function inner () {
370+ // Once `using` syntax is supported, you can use that here, and omit the
371+ // dispose call at the end of this function.
372+ const disposable = asyncLocalStorage .use (store);
373+ asyncLocalStorage .getStore (); // Returns store2
374+ setTimeout (() => {
375+ asyncLocalStorage .getStore (); // Returns store2
376+ }, 200 );
377+ disposable[Symbol .dispose ]();
378+ }
379+
380+ asyncLocalStorage .run (store1, () => {
381+ asyncLocalStorage .getStore (); // Returns store1
382+ inner ();
383+ asyncLocalStorage .getStore (); // Returns store1
384+ });
385+ ```
386+
350387### ` asyncLocalStorage.exit(callback[, ...args]) `
351388
352389<!-- YAML
Original file line number Diff line number Diff line change 22
33const {
44 ReflectApply,
5+ SymbolDispose,
56} = primordials ;
67
78const {
@@ -11,6 +12,19 @@ const {
1112const AsyncContextFrame = require ( 'internal/async_context_frame' ) ;
1213const { AsyncResource } = require ( 'async_hooks' ) ;
1314
15+ class DisposableStore {
16+ #oldFrame = undefined ;
17+
18+ constructor ( store , storage ) {
19+ this . #oldFrame = AsyncContextFrame . current ( ) ;
20+ storage . enterWith ( store ) ;
21+ }
22+
23+ [ SymbolDispose ] ( ) {
24+ AsyncContextFrame . set ( this . #oldFrame) ;
25+ }
26+ }
27+
1428class AsyncLocalStorage {
1529 #defaultValue = undefined ;
1630 #name = undefined ;
@@ -62,6 +76,10 @@ class AsyncLocalStorage {
6276 }
6377 }
6478
79+ use ( data ) {
80+ return new DisposableStore ( data , this ) ;
81+ }
82+
6583 exit ( fn , ...args ) {
6684 return this . run ( undefined , fn , ...args ) ;
6785 }
Original file line number Diff line number Diff line change 77 ObjectIs,
88 ReflectApply,
99 Symbol,
10+ SymbolDispose,
1011} = primordials ;
1112
1213const {
@@ -30,6 +31,31 @@ const storageHook = createHook({
3031 } ,
3132} ) ;
3233
34+ class DisposableStore {
35+ #oldStore = undefined ;
36+ #resource = undefined ;
37+ #kResourceStore = undefined ;
38+
39+ constructor ( store , storage ) {
40+ this . #oldStore = storage . getStore ( ) ;
41+
42+ if ( ObjectIs ( store , this . #oldStore) ) {
43+ return ;
44+ }
45+
46+ this . #kResourceStore = storage . kResourceStore ;
47+ this . #resource = executionAsyncResource ( ) ;
48+ this . #resource[ this . #kResourceStore] = store ;
49+ }
50+
51+ [ SymbolDispose ] ( ) {
52+ if ( this . #resource === undefined ) {
53+ return ;
54+ }
55+ this . #resource[ this . #kResourceStore] = this . #oldStore;
56+ }
57+ }
58+
3359class AsyncLocalStorage {
3460 #defaultValue = undefined ;
3561 #name = undefined ;
@@ -120,6 +146,11 @@ class AsyncLocalStorage {
120146 }
121147 }
122148
149+ use ( store ) {
150+ this . _enable ( ) ;
151+ return new DisposableStore ( store , this ) ;
152+ }
153+
123154 exit ( callback , ...args ) {
124155 if ( ! this . enabled ) {
125156 return ReflectApply ( callback , null , args ) ;
Original file line number Diff line number Diff line change 1+ 'use strict' ;
2+
3+ require ( '../common' ) ;
4+ const assert = require ( 'assert' ) ;
5+ const { AsyncLocalStorage } = require ( 'async_hooks' ) ;
6+
7+ const storage = new AsyncLocalStorage ( ) ;
8+
9+ const store1 = { } ;
10+ const store2 = { } ;
11+ const store3 = { } ;
12+
13+ function inner ( ) {
14+ // TODO(bengl): Once `using` is supported use that here and don't call
15+ // dispose manually later.
16+ const disposable = storage . use ( store2 ) ;
17+ assert . strictEqual ( storage . getStore ( ) , store2 ) ;
18+ storage . enterWith ( store3 ) ;
19+ disposable [ Symbol . dispose ] ( ) ;
20+ }
21+
22+ storage . enterWith ( store1 ) ;
23+ assert . strictEqual ( storage . getStore ( ) , store1 ) ;
24+ inner ( ) ;
25+ assert . strictEqual ( storage . getStore ( ) , store1 ) ;
You can’t perform that action at this time.
0 commit comments