repos / starfx

supercharged async flow control library.
git clone https://github.com/neurosnap/starfx.git

commit
30e8e88
parent
9bffca8
author
Eric Bower
date
2023-09-16 19:09:32 +0000 UTC
refactor(redux): use signal instead of channel
5 files changed,  +35, -50
M mod.ts
M deps.ts
+3, -0
 1@@ -5,6 +5,7 @@ export type {
 2   Port,
 3   Result,
 4   Scope,
 5+  Signal,
 6   Stream,
 7   Subscription,
 8   Task,
 9@@ -13,7 +14,9 @@ export {
10   action,
11   createChannel,
12   createContext,
13+  createQueue,
14   createScope,
15+  createSignal,
16   each,
17   Err,
18   expect,
M mod.ts
+2, -0
 1@@ -7,7 +7,9 @@ export {
 2   action,
 3   createChannel,
 4   createContext,
 5+  createQueue,
 6   createScope,
 7+  createSignal,
 8   each,
 9   Err,
10   getframe,
M redux/fx.ts
+18, -21
 1@@ -1,52 +1,48 @@
 2-import { Action, Channel, Operation } from "../deps.ts";
 3-import { createChannel, createContext, spawn } from "../deps.ts";
 4-import { call, parallel } from "../fx/mod.ts";
 5+import { Action, Operation, Signal } from "../deps.ts";
 6+import { createContext, createSignal, each, spawn } from "../deps.ts";
 7+import { call } from "../fx/mod.ts";
 8 import { ActionPattern, matcher } from "../matcher.ts";
 9 import type { ActionWPayload, AnyAction } from "../types.ts";
10 
11 import type { StoreLike } from "./types.ts";
12 
13-export const ActionContext = createContext<Channel<Action, void>>(
14+export const ActionContext = createContext<Signal<Action, void>>(
15   "redux:action",
16-  createChannel<Action, void>(),
17+  createSignal<Action, void>(),
18 );
19 
20 export const StoreContext = createContext<StoreLike>("redux:store");
21 
22-export function* emit({
23-  channel,
24+export function emit({
25+  signal,
26   action,
27 }: {
28-  channel: Operation<Channel<AnyAction, void>>;
29+  signal: Signal<AnyAction, void>;
30   action: AnyAction | AnyAction[];
31 }) {
32-  const { input } = yield* channel;
33   if (Array.isArray(action)) {
34     if (action.length === 0) {
35       return;
36     }
37-    yield* parallel(action.map((a) => () => input.send(a)));
38+    action.map((a) => signal.send(a));
39   } else {
40-    yield* input.send(action);
41+    signal.send(action);
42   }
43 }
44 
45 export function* once({
46-  channel,
47+  signal,
48   pattern,
49 }: {
50-  channel: Operation<Channel<Action, void>>;
51+  signal: Signal<Action, void>;
52   pattern: ActionPattern;
53 }) {
54-  const { output } = yield* channel;
55-  const msgList = yield* output;
56-  let next = yield* msgList.next();
57-  while (!next.done) {
58+  for (const action of yield* each(signal.stream)) {
59     const match = matcher(pattern);
60-    if (match(next.value)) {
61-      return next.value;
62+    if (match(action)) {
63+      return action;
64     }
65-    next = yield* msgList.next();
66+    yield* each.next;
67   }
68 }
69 
70@@ -57,8 +53,9 @@ export function* select<S, R>(selectorFn: (s: S) => R) {
71 
72 export function take<P>(pattern: ActionPattern): Operation<ActionWPayload<P>>;
73 export function* take(pattern: ActionPattern): Operation<Action> {
74+  const signal = yield* ActionContext;
75   const action = yield* once({
76-    channel: ActionContext,
77+    signal,
78     pattern,
79   });
80   return action as Action;
M redux/middleware.ts
+8, -23
 1@@ -1,36 +1,21 @@
 2-import {
 3-  Action,
 4-  BATCH,
 5-  BatchAction,
 6-  ReducersMapObject,
 7-  Scope,
 8-} from "../deps.ts";
 9+import { BATCH, BatchAction, ReducersMapObject, Scope } from "../deps.ts";
10 import { combineReducers, createScope, enableBatching } from "../deps.ts";
11-import { parallel } from "../fx/mod.ts";
12 import type { AnyAction } from "../types.ts";
13-
14 import { ActionContext, emit, StoreContext } from "./fx.ts";
15 import { reducers as queryReducers } from "./query.ts";
16 import type { StoreLike } from "./types.ts";
17 
18 function* send(action: AnyAction) {
19+  const signal = yield* ActionContext;
20   if (action.type === BATCH) {
21     const actions = action.payload as BatchAction[];
22-    const group = yield* parallel(
23-      actions.map(
24-        (a) =>
25-          function* () {
26-            yield* emit({
27-              channel: ActionContext,
28-              action: a as Action,
29-            });
30-          },
31-      ),
32-    );
33-    yield* group;
34+    emit({
35+      signal,
36+      action: actions,
37+    });
38   } else {
39-    yield* emit({
40-      channel: ActionContext,
41+    emit({
42+      signal,
43       action,
44     });
45   }
M redux/put.test.ts
+4, -6
 1@@ -1,5 +1,5 @@
 2 import { describe, expect, it } from "../test.ts";
 3-import { sleep, spawn } from "../deps.ts";
 4+import { each, sleep, spawn } from "../deps.ts";
 5 
 6 import { ActionContext, put, take } from "./mod.ts";
 7 import { createTestStore } from "./util.ts";
 8@@ -12,11 +12,9 @@ it(putTests, "should send actions through channel", async () => {
 9   function* genFn(arg: string) {
10     yield* spawn(function* () {
11       const actions = yield* ActionContext;
12-      const msgs = yield* actions.output;
13-      let action = yield* msgs.next();
14-      while (!action.done) {
15-        actual.push(action.value.type);
16-        action = yield* msgs.next();
17+      for (const action of yield* each(actions.stream)) {
18+        actual.push(action.type);
19+        yield* each.next;
20       }
21     });
22