@fbltd/async 1.0.23 → 1.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -71,6 +71,7 @@ setInterval(() => {
71
71
  ##### onceStream
72
72
  ##### raceStream
73
73
  ##### next
74
+ ##### reaction
74
75
 
75
76
  #### Framework integrations
76
77
  ##### React
@@ -1,7 +1,7 @@
1
1
  import { PromiseConfiguration } from "../promise-configuration.js";
2
2
  import { DependencyStream } from "./dependency.stream.js";
3
3
  import { baseComparer } from "./utils.js";
4
- import { setDep } from "./global.js";
4
+ import { collectDep } from "./global.js";
5
5
  export class Dependency {
6
6
  _value;
7
7
  reactionPromise;
@@ -29,7 +29,7 @@ export class Dependency {
29
29
  this._set(v);
30
30
  }
31
31
  get value() {
32
- setDep(this);
32
+ collectDep(this);
33
33
  return this._value;
34
34
  }
35
35
  getStream() {
@@ -57,10 +57,7 @@ export class Dependency {
57
57
  return isDisposed;
58
58
  },
59
59
  next: async () => {
60
- if (!this.reactionPromise) {
61
- this.reactionPromise = new PromiseConfiguration();
62
- this._set(this._value);
63
- }
60
+ this.reactionPromise = this.reactionPromise ?? new PromiseConfiguration();
64
61
  await Promise.race([
65
62
  ...externalPromises,
66
63
  this.reactionPromise.promise,
@@ -82,6 +79,30 @@ export class Dependency {
82
79
  }
83
80
  };
84
81
  }
82
+ _race;
83
+ async next(ref = {}) {
84
+ const abortPromise = this.abortPromise;
85
+ if (!this._race) {
86
+ this.reactionPromise = this.reactionPromise ?? new PromiseConfiguration();
87
+ this._race = Promise.race([
88
+ abortPromise.promise,
89
+ this.reactionPromise.promise,
90
+ ]);
91
+ }
92
+ let race = this._race;
93
+ await race;
94
+ this._race = undefined;
95
+ if (abortPromise.isFulfilled) {
96
+ ref.done = true;
97
+ return { done: true };
98
+ }
99
+ return {
100
+ done: false,
101
+ get value() {
102
+ return this.value;
103
+ }
104
+ };
105
+ }
85
106
  dispose() {
86
107
  this.abortPromise.resolve();
87
108
  this.abortPromise = new PromiseConfiguration();
@@ -3,7 +3,7 @@ const global = {
3
3
  dependencies: null
4
4
  };
5
5
  const notImplemented = new Error('Watching while watching is not implemented');
6
- export function watchDeps(fn) {
6
+ export function runFnWithDepCollection(fn) {
7
7
  if (global.watchFlag) {
8
8
  throw notImplemented;
9
9
  }
@@ -17,7 +17,7 @@ export function watchDeps(fn) {
17
17
  result, deps
18
18
  };
19
19
  }
20
- export function setDep(dep) {
20
+ export function collectDep(dep) {
21
21
  if (!global.watchFlag)
22
22
  return;
23
23
  global.dependencies.add(dep);
@@ -1,18 +1,21 @@
1
- import { watchDeps } from "../global.js";
2
- import { symAI } from "../../constants.js";
1
+ import { runFnWithDepCollection } from "../global.js";
3
2
  /**
4
3
  * @deprecated
5
4
  */
6
5
  export function reaction(fn) {
6
+ const ref = { done: false };
7
7
  return {
8
8
  [Symbol.asyncIterator]: () => {
9
- let { result, deps } = watchDeps(fn);
9
+ let { result, deps } = runFnWithDepCollection(fn);
10
10
  return {
11
11
  next: async () => {
12
- const dependencies = Array.from(deps);
13
- const streams = dependencies.map(dep => dep[symAI]());
14
- await Promise.race(streams.map(s => s.next()));
15
- ({ result, deps } = watchDeps(fn));
12
+ await Promise
13
+ .race(Array
14
+ .from(deps)
15
+ .map(dep => dep.next(ref)));
16
+ if (ref.done)
17
+ return ref;
18
+ ({ result, deps } = runFnWithDepCollection(fn));
16
19
  return { done: false, value: result };
17
20
  }
18
21
  };
@@ -11,5 +11,15 @@ export declare class Dependency<T = any> {
11
11
  get value(): T;
12
12
  getStream(this: Dependency<T>): DependencyStream<T>;
13
13
  [Symbol.asyncIterator](this: Dependency<T>, thisStreamConfig?: IThisStreamConfig): IStreamIterator<T>;
14
+ private _race;
15
+ next(ref?: {
16
+ done?: boolean;
17
+ }): Promise<{
18
+ done: true;
19
+ value?: never;
20
+ } | {
21
+ done: boolean;
22
+ readonly value: T;
23
+ }>;
14
24
  dispose(this: Dependency<T>): void;
15
25
  }
@@ -3,9 +3,9 @@ declare const global: {
3
3
  watchFlag: boolean;
4
4
  dependencies: Set<Dependency>;
5
5
  };
6
- export declare function watchDeps<T>(fn: () => T): {
6
+ export declare function runFnWithDepCollection<T>(fn: () => T): {
7
7
  result: T;
8
8
  deps: typeof global.dependencies;
9
9
  };
10
- export declare function setDep(dep: Dependency): void;
10
+ export declare function collectDep(dep: Dependency): void;
11
11
  export {};
@@ -4,6 +4,9 @@
4
4
  export declare function reaction<T>(fn: () => T): {
5
5
  [Symbol.asyncIterator]: () => {
6
6
  next: () => Promise<{
7
+ done: true;
8
+ value?: never;
9
+ } | {
7
10
  done: boolean;
8
11
  value: T;
9
12
  }>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fbltd/async",
3
- "version": "1.0.23",
3
+ "version": "1.0.24",
4
4
  "description": "Miscellaneous async utils",
5
5
  "homepage": "https://github.com/GlennMiller1991/async",
6
6
  "type": "module",
@@ -21,8 +21,8 @@
21
21
  "tsconfig.json"
22
22
  ],
23
23
  "scripts": {
24
- "clearDist": "rm dist -r || true",
25
- "clearModules": "rm node_modules -r || true",
24
+ "clearDist": "rm -r dist || true",
25
+ "clearModules": "rm -r node_modules || true",
26
26
  "clearAll": "npm run clearDist && npm run clearModules",
27
27
  "build": "npm run clearAll && npm i && mkdir dist && tsc",
28
28
  "test": "node --expose-gc node_modules/.bin/jest --config=./__tests__/jest.config.cjs",