File tree Expand file tree Collapse file tree 5 files changed +161
-3
lines changed
lib/internal/async_local_storage Expand file tree Collapse file tree 5 files changed +161
-3
lines changed Original file line number Diff line number Diff line change @@ -116,13 +116,16 @@ Each instance of `AsyncLocalStorage` maintains an independent storage context.
116
116
Multiple instances can safely exist simultaneously without risk of interfering
117
117
with each other's data.
118
118
119
- ### ` new AsyncLocalStorage() `
119
+ ### ` new AsyncLocalStorage([options] ) `
120
120
121
121
<!-- YAML
122
122
added:
123
123
- v13.10.0
124
124
- v12.17.0
125
125
changes:
126
+ - version: REPLACEME
127
+ pr-url: https://github.com/nodejs/node/pull/00000
128
+ description: Add `defaultValue` and `name` options.
126
129
- version:
127
130
- v19.7.0
128
131
- v18.16.0
@@ -135,6 +138,10 @@ changes:
135
138
description: Add option onPropagate.
136
139
-->
137
140
141
+ * ` options ` {Object}
142
+ * ` defaultValue ` {any} The default value to be used when no store is provided.
143
+ * ` name ` {string} A name for the ` AsyncLocalStorage ` value.
144
+
138
145
Creates a new instance of ` AsyncLocalStorage ` . Store is only provided within a
139
146
` run() ` call or after an ` enterWith() ` call.
140
147
@@ -286,6 +293,16 @@ emitter.emit('my-event');
286
293
asyncLocalStorage .getStore (); // Returns the same object
287
294
```
288
295
296
+ ### ` asyncLocalStorage.name `
297
+
298
+ <!-- YAML
299
+ added: REPLACEME
300
+ -->
301
+
302
+ * {string}
303
+
304
+ The name of the ` AsyncLocalStorage ` instance if provided.
305
+
289
306
### ` asyncLocalStorage.run(store, callback[, ...args]) `
290
307
291
308
<!-- YAML
Original file line number Diff line number Diff line change @@ -4,10 +4,38 @@ const {
4
4
ReflectApply,
5
5
} = primordials ;
6
6
7
+ const {
8
+ validateObject,
9
+ validateString,
10
+ } = require ( 'internal/validators' ) ;
11
+
7
12
const AsyncContextFrame = require ( 'internal/async_context_frame' ) ;
8
13
const { AsyncResource } = require ( 'async_hooks' ) ;
9
14
10
15
class AsyncLocalStorage {
16
+ #defaultValue = undefined ;
17
+ #name = undefined ;
18
+
19
+ /**
20
+ * @typedef {object } AsyncLocalStorageOptions
21
+ * @property {any } [defaultValue] - The default value to use when no value is set.
22
+ * @property {string } [name] - The name of the storage.
23
+ */
24
+ /**
25
+ * @param {AsyncLocalStorageOptions } [options]
26
+ */
27
+ constructor ( options = { } ) {
28
+ validateObject ( options , 'options' ) ;
29
+ this . #defaultValue = options . defaultValue ;
30
+
31
+ if ( options . name !== undefined ) {
32
+ this . #name = `${ options . name } ` ;
33
+ }
34
+ }
35
+
36
+ /** @type {string } */
37
+ get name ( ) { return this . #name || '' ; }
38
+
11
39
static bind ( fn ) {
12
40
return AsyncResource . bind ( fn ) ;
13
41
}
@@ -40,7 +68,11 @@ class AsyncLocalStorage {
40
68
}
41
69
42
70
getStore ( ) {
43
- return AsyncContextFrame . current ( ) ?. get ( this ) ;
71
+ const frame = AsyncContextFrame . current ( ) ;
72
+ if ( ! frame ?. has ( this ) ) {
73
+ return this . #defaultValue;
74
+ }
75
+ return frame ?. get ( this ) ;
44
76
}
45
77
}
46
78
Original file line number Diff line number Diff line change 9
9
Symbol,
10
10
} = primordials ;
11
11
12
+ const {
13
+ validateObject,
14
+ validateString,
15
+ } = require ( 'internal/validators' ) ;
16
+
12
17
const {
13
18
AsyncResource,
14
19
createHook,
@@ -27,11 +32,31 @@ const storageHook = createHook({
27
32
} ) ;
28
33
29
34
class AsyncLocalStorage {
30
- constructor ( ) {
35
+ #defaultValue = undefined ;
36
+ #name = undefined ;
37
+
38
+ /**
39
+ * @typedef {object } AsyncLocalStorageOptions
40
+ * @property {any } [defaultValue] - The default value to use when no value is set.
41
+ * @property {string } [name] - The name of the storage.
42
+ */
43
+ /**
44
+ * @param {AsyncLocalStorageOptions } [options]
45
+ */
46
+ constructor ( options = { } ) {
31
47
this . kResourceStore = Symbol ( 'kResourceStore' ) ;
32
48
this . enabled = false ;
49
+ validateObject ( options , 'options' ) ;
50
+ this . #defaultValue = options . defaultValue ;
51
+
52
+ if ( options . name !== undefined ) {
53
+ this . #name = `${ options . name } ` ;
54
+ }
33
55
}
34
56
57
+ /** @type {string } */
58
+ get name ( ) { return this . #name || '' ; }
59
+
35
60
static bind ( fn ) {
36
61
return AsyncResource . bind ( fn ) ;
37
62
}
@@ -109,8 +134,12 @@ class AsyncLocalStorage {
109
134
getStore ( ) {
110
135
if ( this . enabled ) {
111
136
const resource = executionAsyncResource ( ) ;
137
+ if ( ! ( this . kResourceStore in resource ) ) {
138
+ return this . #defaultValue;
139
+ }
112
140
return resource [ this . kResourceStore ] ;
113
141
}
142
+ return this . #defaultValue;
114
143
}
115
144
}
116
145
Original file line number Diff line number Diff line change
1
+ // Flags: --no-async-context-frame
2
+ 'use strict' ;
3
+
4
+ require ( '../common' ) ;
5
+
6
+ const {
7
+ AsyncLocalStorage,
8
+ } = require ( 'async_hooks' ) ;
9
+
10
+ const {
11
+ strictEqual,
12
+ throws,
13
+ } = require ( 'assert' ) ;
14
+
15
+ // ============================================================================
16
+ // The defaultValue option
17
+ const als1 = new AsyncLocalStorage ( ) ;
18
+ strictEqual ( als1 . getStore ( ) , undefined , 'value should be undefined' ) ;
19
+
20
+ const als2 = new AsyncLocalStorage ( { defaultValue : 'default' } ) ;
21
+ strictEqual ( als2 . getStore ( ) , 'default' , 'value should be "default"' ) ;
22
+
23
+ const als3 = new AsyncLocalStorage ( { defaultValue : 42 } ) ;
24
+ strictEqual ( als3 . getStore ( ) , 42 , 'value should be 42' ) ;
25
+
26
+ const als4 = new AsyncLocalStorage ( { defaultValue : null } ) ;
27
+ strictEqual ( als4 . getStore ( ) , null , 'value should be null' ) ;
28
+
29
+ throws ( ( ) => new AsyncLocalStorage ( null ) , {
30
+ code : 'ERR_INVALID_ARG_TYPE' ,
31
+ } ) ;
32
+
33
+ // ============================================================================
34
+ // The name option
35
+
36
+ const als5 = new AsyncLocalStorage ( { name : 'test' } ) ;
37
+ strictEqual ( als5 . name , 'test' ) ;
38
+
39
+ const als6 = new AsyncLocalStorage ( ) ;
40
+ strictEqual ( als6 . name , '' ) ;
Original file line number Diff line number Diff line change
1
+ // Flags: --async-context-frame
2
+ 'use strict' ;
3
+
4
+ require ( '../common' ) ;
5
+
6
+ const {
7
+ AsyncLocalStorage,
8
+ } = require ( 'async_hooks' ) ;
9
+
10
+ const {
11
+ strictEqual,
12
+ throws,
13
+ } = require ( 'assert' ) ;
14
+
15
+ // ============================================================================
16
+ // The defaultValue option
17
+ const als1 = new AsyncLocalStorage ( ) ;
18
+ strictEqual ( als1 . getStore ( ) , undefined , 'value should be undefined' ) ;
19
+
20
+ const als2 = new AsyncLocalStorage ( { defaultValue : 'default' } ) ;
21
+ strictEqual ( als2 . getStore ( ) , 'default' , 'value should be "default"' ) ;
22
+
23
+ const als3 = new AsyncLocalStorage ( { defaultValue : 42 } ) ;
24
+ strictEqual ( als3 . getStore ( ) , 42 , 'value should be 42' ) ;
25
+
26
+ const als4 = new AsyncLocalStorage ( { defaultValue : null } ) ;
27
+ strictEqual ( als4 . getStore ( ) , null , 'value should be null' ) ;
28
+
29
+ throws ( ( ) => new AsyncLocalStorage ( null ) , {
30
+ code : 'ERR_INVALID_ARG_TYPE' ,
31
+ } ) ;
32
+
33
+ // ============================================================================
34
+ // The name option
35
+
36
+ const als5 = new AsyncLocalStorage ( { name : 'test' } ) ;
37
+ strictEqual ( als5 . name , 'test' ) ;
38
+
39
+ const als6 = new AsyncLocalStorage ( ) ;
40
+ strictEqual ( als6 . name , '' ) ;
You can’t perform that action at this time.
0 commit comments