async_hooks: add sync enterWith to ALS · nodejs/node@4d5981b

3 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -950,6 +950,48 @@ If this method is called outside of an asynchronous context initialized by

950950

calling `asyncLocalStorage.run` or `asyncLocalStorage.runAndReturn`, it will

951951

return `undefined`.

952952
953+

### `asyncLocalStorage.enterWith(store)`

954+

<!-- YAML

955+

added: REPLACEME

956+

-->

957+
958+

* `store` {any}

959+
960+

Calling `asyncLocalStorage.enterWith(store)` will transition into the context

961+

for the remainder of the current synchronous execution and will persist

962+

through any following asynchronous calls.

963+
964+

Example:

965+
966+

```js

967+

const store = { id: 1 };

968+

asyncLocalStorage.enterWith(store);

969+

asyncLocalStorage.getStore(); // Returns the store object

970+

someAsyncOperation(() => {

971+

asyncLocalStorage.getStore(); // Returns the same object

972+

});

973+

```

974+
975+

This transition will continue for the _entire_ synchronous execution.

976+

This means that if, for example, the context is entered within an event

977+

handler subsequent event handlers will also run within that context unless

978+

specifically bound to another context with an `AsyncResource`.

979+
980+

```js

981+

const store = { id: 1 };

982+
983+

emitter.on('my-event', () => {

984+

asyncLocalStorage.enterWith(store);

985+

});

986+

emitter.on('my-event', () => {

987+

asyncLocalStorage.getStore(); // Returns the same object

988+

});

989+
990+

asyncLocalStorage.getStore(); // Returns undefined

991+

emitter.emit('my-event');

992+

asyncLocalStorage.getStore(); // Returns the same object

993+

```

994+
953995

### `asyncLocalStorage.run(store, callback[, ...args])`

954996

<!-- YAML

955997

added: v13.10.0

Original file line numberDiff line numberDiff line change

@@ -245,7 +245,7 @@ class AsyncLocalStorage {

245245

}

246246

}

247247
248-

_enter(store) {

248+

enterWith(store) {

249249

if (!this.enabled) {

250250

this.enabled = true;

251251

storageList.push(this);

@@ -258,7 +258,7 @@ class AsyncLocalStorage {

258258

runSyncAndReturn(store, callback, ...args) {

259259

const resource = executionAsyncResource();

260260

const outerStore = resource[this.kResourceStore];

261-

this._enter(store);

261+

this.enterWith(store);

262262

try {

263263

return callback(...args);

264264

} finally {

@@ -288,7 +288,7 @@ class AsyncLocalStorage {

288288

run(store, callback, ...args) {

289289

const resource = executionAsyncResource();

290290

const outerStore = resource[this.kResourceStore];

291-

this._enter(store);

291+

this.enterWith(store);

292292

process.nextTick(callback, ...args);

293293

resource[this.kResourceStore] = outerStore;

294294

}

Original file line numberDiff line numberDiff line change

@@ -0,0 +1,20 @@

1+

'use strict';

2+

require('../common');

3+

const assert = require('assert');

4+

const { AsyncLocalStorage } = require('async_hooks');

5+
6+

const asyncLocalStorage = new AsyncLocalStorage();

7+
8+

setImmediate(() => {

9+

const store = { foo: 'bar' };

10+

asyncLocalStorage.enterWith(store);

11+
12+

assert.strictEqual(asyncLocalStorage.getStore(), store);

13+

setTimeout(() => {

14+

assert.strictEqual(asyncLocalStorage.getStore(), store);

15+

}, 10);

16+

});

17+
18+

setTimeout(() => {

19+

assert.strictEqual(asyncLocalStorage.getStore(), undefined);

20+

}, 10);