async-chain-list
v0.0.3
Published
Async Chain List Data Structure
Maintainers
Readme
Async Chain List
A lightweight, elegant data structure for managing asynchronous data streams in JavaScript/TypeScript. AsyncChain provides a linked-list-based approach to handle producer-consumer patterns with full support for async iteration.
Features
- 🔗 Linked List Structure: Efficient memory usage with automatic garbage collection
- ⚡ Async/Await Support: Native async iterator implementation
- 🎯 Type Safe: Full TypeScript support with generics
- 🔄 Producer-Consumer Pattern: Perfect for event-driven architectures
- 📦 Zero Dependencies: Minimal footprint
- 🎨 Flexible: Can be backed by any task object (e.g., EventTarget)
Basic Usage
Simple Producer-Consumer
import AsyncChain from "async-chain-list";
const chain = new AsyncChain<number>();
// Producer: Push values to the chain
async function producer() {
for (let i = 0; i < 5; i++) {
chain.push(i);
await delay(100);
}
chain.close(); // Signal end of data
}
// Consumer: Iterate through values
async function consumer() {
for await (const value of chain) {
console.log("Received:", value);
}
}
await Promise.all([producer(), consumer()]);Event-Driven Usage
AsyncChain can be backed by any task object, making it perfect for event-driven patterns:
import AsyncChain from "async-chain-list";
const eventTarget = new EventTarget();
const chain = new AsyncChain<number, EventTarget>(eventTarget);
// Connect events to the chain
chain.task.addEventListener("data", (e) =>
chain.push((e as CustomEvent).detail),
);
chain.task.addEventListener("close", () => chain.close());
// Producer dispatches events
async function producer() {
for (let i = 0; i < 5; i++) {
chain.task?.dispatchEvent(new CustomEvent("data", { detail: i }));
await delay(100);
}
chain.task?.dispatchEvent(new Event("close"));
}
// Consumer uses async iteration
async function consumer() {
for await (const value of chain) {
console.log("Received:", value);
}
}
await Promise.all([producer(), consumer()]);API Reference
Constructor
new AsyncChain<T, P>(task?: P)T: Type of values in the chainP: Type of the backing task object (optional)task: Optional task object that backs the chain (e.g., EventTarget)
Methods
push(value: T): AsyncChain<T, P>
Push a new value to the end of the chain. Returns the new back node.
const newBack = chain.push(42);Throws: Error if the chain is already closed.
close(): void
Close the chain to block further pushes and signal the end to consumers.
chain.close();Properties
back: AsyncChain<T, P>
Get the end node of the chain (useful for pushing values).
const endNode = chain.back;current_length: number
Get the count of values already pushed to the chain from the current node.
const count = chain.current_length;task?: P
Read-only reference to the backing task object passed during construction.
const eventTarget = chain.task;Iterators
Async Iterator
AsyncChain implements Symbol.asyncIterator for use with for await...of:
for await (const value of chain) {
console.log(value);
}Sync Iterator
Synchronously iterate through already-pushed values:
for (const value of chain) {
console.log(value); // null for pending values
}current_values(): Generator<T>
Generator that yields all values already pushed to the chain from the current node:
for (const value of chain.current_values()) {
console.log(value); // Only existing values, no waiting
}How It Works
AsyncChain is implemented as a linked list where:
- Each node contains a value and a reference to the next node
- The
nextreference can be a Promise (pending), another node (data available), or null (end of chain) - Multiple consumers can iterate the same chain independently
- Memory is automatically reclaimed by JavaScript's garbage collector
Use Cases
- Event Streams: Convert event-based APIs to async iterables
- Message Queues: Simple producer-consumer implementations
- Data Pipelines: Stream processing with async/await
- WebSocket/SSE: Handle streaming data from network sources
- Rate-Limited APIs: Queue and process requests asynchronously
TypeScript Support
Full TypeScript support with generic types:
interface Message {
id: number;
content: string;
}
const chain = new AsyncChain<Message>();
chain.push({ id: 1, content: "Hello" }); // Type-safeLicense
MIT © Yuxuan Zhang
