Skip to content

zhangyx1998/async-chain-list

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

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)

Installation

npm install async-chain

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 chain
  • P: 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 next reference 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-safe

License

MIT Β© Yuxuan Zhang

Repository

github.com/zhangyx1998/async-chain-list

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published