Skip to content

Instantly share code, notes, and snippets.

@markmals
Created December 4, 2023 16:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markmals/037ed24f5557c73d070e56b4bf7c7cae to your computer and use it in GitHub Desktop.
Save markmals/037ed24f5557c73d070e56b4bf7c7cae to your computer and use it in GitHub Desktop.
Create an async iterable stream of values from a Solid.js signal effect
import { createMemo, createEffect } from 'solid-js';
export async function* createEffectStream<T>(fn: () => T) {
let promises: Promise<T>[] = [];
let resolve: (value: T) => void;
promises.push(
new Promise(r => {
resolve = r;
}),
);
let memoized = createMemo(fn);
createEffect(() => {
resolve(memoized());
promises.push(
new Promise(r => {
resolve = r;
}),
);
});
for (let promise of promises) {
let value = await promise;
delete promises[promises.indexOf(promise)];
yield value;
}
}
@markmals
Copy link
Author

markmals commented Dec 4, 2023

Usage:

import { createSignal, createRoot } from 'solid-js';
import { createEffectStream } from './effect-stream.ts';

let [count, setCount] = createSignal(0);
let double = () => count() * 2;

async function processChanges() {
    let valueStream = createEffectStream(() => `Double ${count()} is ${double()}`);

    for await (let value of valueStream) {
        console.log(value);
    }
}

createRoot(processChanges);

setInterval(() => setCount(c => c + 1), 1000);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment