diff options
-rw-r--r-- | doc/api/async_hooks.md | 42 | ||||
-rw-r--r-- | lib/async_hooks.js | 6 | ||||
-rw-r--r-- | test/async-hooks/test-async-local-storage-enter-with.js | 20 |
3 files changed, 65 insertions, 3 deletions
diff --git a/doc/api/async_hooks.md b/doc/api/async_hooks.md index 5990291716..f02d3ff755 100644 --- a/doc/api/async_hooks.md +++ b/doc/api/async_hooks.md @@ -950,6 +950,48 @@ If this method is called outside of an asynchronous context initialized by calling `asyncLocalStorage.run` or `asyncLocalStorage.runAndReturn`, it will return `undefined`. +### `asyncLocalStorage.enterWith(store)` +<!-- YAML +added: REPLACEME +--> + +* `store` {any} + +Calling `asyncLocalStorage.enterWith(store)` will transition into the context +for the remainder of the current synchronous execution and will persist +through any following asynchronous calls. + +Example: + +```js +const store = { id: 1 }; +asyncLocalStorage.enterWith(store); +asyncLocalStorage.getStore(); // Returns the store object +someAsyncOperation(() => { + asyncLocalStorage.getStore(); // Returns the same object +}); +``` + +This transition will continue for the _entire_ synchronous execution. +This means that if, for example, the context is entered within an event +handler subsequent event handlers will also run within that context unless +specifically bound to another context with an `AsyncResource`. + +```js +const store = { id: 1 }; + +emitter.on('my-event', () => { + asyncLocalStorage.enterWith(store); +}); +emitter.on('my-event', () => { + asyncLocalStorage.getStore(); // Returns the same object +}); + +asyncLocalStorage.getStore(); // Returns undefined +emitter.emit('my-event'); +asyncLocalStorage.getStore(); // Returns the same object +``` + ### `asyncLocalStorage.run(store, callback[, ...args])` <!-- YAML added: v13.10.0 diff --git a/lib/async_hooks.js b/lib/async_hooks.js index bd3cd57d02..d676f6dfcb 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -245,7 +245,7 @@ class AsyncLocalStorage { } } - _enter(store) { + enterWith(store) { if (!this.enabled) { this.enabled = true; storageList.push(this); @@ -258,7 +258,7 @@ class AsyncLocalStorage { runSyncAndReturn(store, callback, ...args) { const resource = executionAsyncResource(); const outerStore = resource[this.kResourceStore]; - this._enter(store); + this.enterWith(store); try { return callback(...args); } finally { @@ -288,7 +288,7 @@ class AsyncLocalStorage { run(store, callback, ...args) { const resource = executionAsyncResource(); const outerStore = resource[this.kResourceStore]; - this._enter(store); + this.enterWith(store); process.nextTick(callback, ...args); resource[this.kResourceStore] = outerStore; } diff --git a/test/async-hooks/test-async-local-storage-enter-with.js b/test/async-hooks/test-async-local-storage-enter-with.js new file mode 100644 index 0000000000..736dd83f85 --- /dev/null +++ b/test/async-hooks/test-async-local-storage-enter-with.js @@ -0,0 +1,20 @@ +'use strict'; +require('../common'); +const assert = require('assert'); +const { AsyncLocalStorage } = require('async_hooks'); + +const asyncLocalStorage = new AsyncLocalStorage(); + +setImmediate(() => { + const store = { foo: 'bar' }; + asyncLocalStorage.enterWith(store); + + assert.strictEqual(asyncLocalStorage.getStore(), store); + setTimeout(() => { + assert.strictEqual(asyncLocalStorage.getStore(), store); + }, 10); +}); + +setTimeout(() => { + assert.strictEqual(asyncLocalStorage.getStore(), undefined); +}, 10); |