Skip to content

Commit dabacf5

Browse files
committed
feat: add callback
1 parent fe0290a commit dabacf5

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
`node-simple-context` is an helper to create a context in node.
44

5-
This library is highly inspired by [nctx](https://github.com/devthejo/nctx). You definitely should check it out!
5+
This library is highly inspired by [nctx](https://github.com/devthejo/nctx). You definitely should check it out! Thanks to @devthejo for his help 💪
66

77
## Installation
88

@@ -51,6 +51,8 @@ console.log(contextA.get<string>('foo')); // bar
5151

5252
Thanks to [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html) api, you can `fork` your context in promise or async functions. As you can see below:
5353

54+
> You can also pass a callback in `fork` method to runs a function synchronously within a context and returns its return value which uses [run method from AsyncLocalStorage](https://nodejs.org/api/async_context.html#asynclocalstoragerunstore-callback-args) (cf. [example](./src/__tests__/context.test.ts#L134))
55+
5456
```ts
5557
const context = createSimpleContext();
5658

src/__tests__/context.test.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import EventEmitter from 'events';
12
import { createSimpleContext, SimpleContext } from '..';
23

34
describe('SimpleContext', () => {
@@ -129,4 +130,68 @@ describe('SimpleContext', () => {
129130
]);
130131
expect(res).toStrictEqual(['foo=tata', 'foo=toto', 'foo=titi', 'foo=tutu']);
131132
});
133+
134+
it('should work if the values are wrapped in a callback run', async () => {
135+
function Deferred() {
136+
let resolve;
137+
let reject;
138+
const promise = new Promise((thisResolve, thisReject) => {
139+
resolve = thisResolve;
140+
reject = thisReject;
141+
});
142+
return Object.assign(promise, { resolve, reject });
143+
}
144+
const emitter = new EventEmitter();
145+
146+
const context = createSimpleContext();
147+
148+
const deferredTiti: any = Deferred();
149+
const deferredToto: any = Deferred();
150+
emitter.on('titi', () => {
151+
context.fork(() => {
152+
context.set('foo', 'titi2');
153+
});
154+
});
155+
emitter.on('toto', () => {
156+
context.fork(() => {
157+
context.set('foo', 'toto2');
158+
});
159+
});
160+
161+
setTimeout(() => {
162+
context.fork(() => {
163+
context.set('foo', 'titi');
164+
emitter.emit('titi');
165+
setTimeout(() => {
166+
deferredTiti.resolve(context.get('foo'));
167+
}, 50);
168+
});
169+
}, 100);
170+
setTimeout(() => {
171+
context.fork(() => {
172+
context.set('foo', 'toto');
173+
emitter.emit('toto');
174+
setTimeout(() => {
175+
deferredToto.resolve(context.get('foo'));
176+
}, 50);
177+
});
178+
}, 200);
179+
180+
expect([await deferredTiti, await deferredToto]).toStrictEqual([
181+
'titi',
182+
'toto',
183+
]);
184+
});
185+
186+
it('should return good value with the callback', async () => {
187+
const context = createSimpleContext();
188+
189+
const string = context
190+
.fork(() => {
191+
return 'hello';
192+
})
193+
.toUpperCase();
194+
195+
expect(string).toBe('HELLO');
196+
});
132197
});

src/context.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ export class SimpleContext {
1616
return this.setForkProperty<T>(key, value);
1717
}
1818

19-
public fork(): SimpleContext {
19+
public fork<T>(callback: () => T): T;
20+
public fork(): SimpleContext;
21+
public fork<T>(callback?: () => T): SimpleContext | T {
2022
const forkedProperties = { ...this.properties };
23+
if (callback) {
24+
return this.asyncLocalStorage.run(forkedProperties, callback);
25+
}
2126
this.asyncLocalStorage.enterWith(forkedProperties);
2227
return this;
2328
}

0 commit comments

Comments
 (0)