@@ -713,6 +713,91 @@ yield* ensure(function*() {
713713});
714714```
715715
716+ ### interval() - Repeated Timed Stream
717+
718+ Create an infinite stream that emits at regular intervals:
719+
720+ ```js
721+ import { main, each, interval } from 'effection';
722+
723+ await main(function*() {
724+ let startTime = Date.now();
725+
726+ for (let _ of yield* each(interval(1000))) {
727+ let elapsed = Date.now() - startTime;
728+ console.log(`elapsed: ${elapsed}ms`);
729+ yield* each.next();
730+ }
731+ });
732+ ```
733+
734+ ### createQueue() - Buffered Queue
735+
736+ Unlike channels (which drop messages with no subscribers), queues buffer items. Items added before a listener exists will still be received:
737+
738+ ```js
739+ import { main, createQueue } from 'effection';
740+
741+ await main(function*() {
742+ let queue = createQueue<string, void>();
743+
744+ // Add items BEFORE listening - they're queued
745+ queue.add("first");
746+ queue.add("second");
747+
748+ // Now consume - items are still there
749+ let next = yield* queue.next();
750+ console.log(next.value); // "first"
751+
752+ next = yield* queue.next();
753+ console.log(next.value); // "second"
754+
755+ queue.close(); // Signal end of queue
756+ });
757+ ```
758+
759+ **Queue vs Channel:**
760+ - `createChannel()` - unbuffered, messages dropped if no subscriber
761+ - `createQueue()` - buffered, messages queued until consumed
762+
763+ ### exit() - Exit main() Program
764+
765+ Immediately halt and exit the program with a status code. Only works inside `main()`:
766+
767+ ```js
768+ import { main, exit } from 'effection';
769+
770+ await main(function*() {
771+ if (invalidArgs()) {
772+ yield* exit(1, "invalid arguments"); // Exits with code 1
773+ }
774+
775+ // ... normal execution
776+ yield* exit(0); // Success
777+ });
778+ ```
779+
780+ **Warning:** Never use `process.exit()` or `Deno.exit()` directly—they skip cleanup. Always use `yield* exit()`.
781+
782+ ### subscribe() / stream() - Convert Async Iterables
783+
784+ Convert JavaScript `AsyncIterator`/`AsyncIterable` to Effection types:
785+
786+ ```js
787+ import { subscribe, stream } from 'effection';
788+
789+ // Convert AsyncIterator to Subscription
790+ let subscription = subscribe(asyncIterator);
791+ let { value } = yield* subscription.next();
792+
793+ // Convert AsyncIterable to Stream
794+ let myStream = stream(asyncIterable);
795+ for (let item of yield* each(myStream)) {
796+ console.log(item);
797+ yield* each.next();
798+ }
799+ ```
800+
716801---
717802
718803## 12. Result and Maybe Types
@@ -846,9 +931,11 @@ This makes execution more predictable but may affect timing-sensitive code. Add
846931- `scoped()` - Isolate effects, clean up immediately when block exits
847932
848933**Streams:**
849- - `createChannel()` - Create stream with send() method
934+ - `createChannel()` - Create unbuffered stream with send() method
935+ - `createQueue()` - Create buffered queue (items persist without subscribers)
850936- `each(stream)` - Loop over stream values (requires `yield* each.next()`)
851937- `createSignal()` - Stream from external events
938+ - `interval(ms)` - Stream that emits at regular intervals
852939
853940**Events (EventTarget only):**
854941- `once(target, name)` - Wait for single event
@@ -863,6 +950,11 @@ This makes execution more predictable but may affect timing-sensitive code. Add
863950- `run(operation)` - Operation → Promise (use in async context)
864951- `call(fn)` - Invoke function as operation (v4: no longer establishes boundaries)
865952- `constant(value)` - Wrap constant value as operation
953+ - `subscribe(asyncIterator)` - AsyncIterator → Subscription
954+ - `stream(asyncIterable)` - AsyncIterable → Stream
955+
956+ **Program control (main() only):**
957+ - `exit(code, msg?)` - Exit program with status code (use instead of process.exit)
866958
867959**Remember:**
868960- Use `yield*` not `await` (inside operations)
0 commit comments