Skip to content

Commit

Permalink
Explicit create() and run()
Browse files Browse the repository at this point in the history
Signed-off-by: Matteo Collina <[email protected]>
  • Loading branch information
mcollina committed May 21, 2024
1 parent f7219d8 commit adbec63
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 155 deletions.
41 changes: 24 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,43 @@ npm i asyncforge
## Usage

```js
import { memo } from 'asyncforge'
import { create, memo } from 'asyncforge.js'

const a = memo()
const b = memo()

a.set(42)
b.set(123)
const store = create()

// simulate an event loop turn
setImmediate(() => {
console.log('-- first event loop turn --')
console.log('a', a())
console.log('b', b())
store.run(() => {
a.set(42)
b.set(123)

b.set(456)
// simulate an event loop turn
setImmediate(() => {
console.log('-- third event loop turn --')
console.log('-- first event loop turn --')
console.log('a', a())
console.log('b', b())
})
})

a.set(43)
b.set(321)
create(() => {
a.set(43)
b.set(321)

// simulate an event loop turn
setImmediate(() => {
console.log('-- second event loop turn --')
console.log('a', a())
console.log('b', b())
// simulate an event loop turn
setImmediate(() => {
console.log('-- second event loop turn --')
console.log('a', a())
console.log('b', b())

store.run(() => {
setImmediate(() => {
console.log('-- third event loop turn --')
console.log('a', a())
console.log('b', b())
})
})
})
})
```

Expand Down
8 changes: 6 additions & 2 deletions asyncforge.d.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
declare namespace asyncforge {
export function start(): void;
interface Store {
run<T>(fn: () => T) : T;
}

export function create () : Store;

export function memo<T extends unknown>(
name?: string
): {
(): T;
key: symbol;
set: (value: T) => void;
};
export function setAll(memos: Record<symbol, unknown>): void;
}

export = asyncforge
46 changes: 27 additions & 19 deletions asyncforge.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,24 @@ const { AsyncLocalStorage } = require('node:async_hooks')

const asyncLocalStorage = new AsyncLocalStorage()

function start () {
const store = Object.create(null)
asyncLocalStorage.enterWith(store)
class Store {
#internal

constructor (internal) {
this.#internal = internal
}

run (fn) {
return asyncLocalStorage.run(this.#internal, fn)
}
}

function create (fn) {
const store = new Store(Object.create(null))
if (fn) {
store.run(fn)
}
return store
}

let memoCounter = 0
Expand All @@ -18,16 +33,20 @@ function memo (name) {
function get () {
const store = asyncLocalStorage.getStore()
if (!store) {
throw new Error(`asyncforge store is not initialized for ${name}`)
throw new Error('asyncforge store has not been created')
}
return store[sym]
}

function set (value) {
let store = asyncLocalStorage.getStore()
store = Object.create(store || null)
const store = asyncLocalStorage.getStore()
if (!store) {
throw new Error('asyncforge store has not been created')
}
if (Object.hasOwnProperty.call(store, sym)) {
throw new Error(`asyncforge store already initialized for ${name}`)
}
store[sym] = value
asyncLocalStorage.enterWith(store)
}

get.set = set
Expand All @@ -36,16 +55,5 @@ function memo (name) {
return get
}

function setAll (memos) {
let store = asyncLocalStorage.getStore()
store = Object.create(store || null)
const keys = Object.getOwnPropertySymbols(memos)
for (const key of keys) {
store[key] = memos[key]
}
asyncLocalStorage.enterWith(store)
}

module.exports.create = create
module.exports.memo = memo
module.exports.start = start
module.exports.setAll = setAll
14 changes: 7 additions & 7 deletions asyncforge.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { expectError, expectType } from "tsd";
import { start, memo, setAll } from ".";
import { create, memo } from ".";
import type { Store } from ".";

expectType<() => void>(start);
expectType<() => Store>(create);

const store = create();

expectType<number>(store.run(() => 42));

// memo
const memoNum = memo<number>();
expectType<symbol>(memoNum.key);
expectType<void>(memoNum.set(123));
expectType<number>(memoNum());
expectError<void>(memoNum.set("wrong"));

// setAll
const test = memo<string>();
expectType<void>(setAll({ [test.key]: 42 }));
expectError<void>(setAll({ wrong: 42 }));
41 changes: 24 additions & 17 deletions example.mjs
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
import { memo } from './asyncforge.js'
import { create, memo } from './asyncforge.js'

const a = memo()
const b = memo()

a.set(42)
b.set(123)
const store = create()

// simulate an event loop turn
setImmediate(() => {
console.log('-- first event loop turn --')
console.log('a', a())
console.log('b', b())
store.run(() => {
a.set(42)
b.set(123)

b.set(456)
// simulate an event loop turn
setImmediate(() => {
console.log('-- third event loop turn --')
console.log('-- first event loop turn --')
console.log('a', a())
console.log('b', b())
})
})

a.set(43)
b.set(321)
create(() => {
a.set(43)
b.set(321)

// simulate an event loop turn
setImmediate(() => {
console.log('-- second event loop turn --')
console.log('a', a())
console.log('b', b())
// simulate an event loop turn
setImmediate(() => {
console.log('-- second event loop turn --')
console.log('a', a())
console.log('b', b())

store.run(() => {
setImmediate(() => {
console.log('-- third event loop turn --')
console.log('a', a())
console.log('b', b())
})
})
})
})
Loading

0 comments on commit adbec63

Please sign in to comment.