npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xstd/listener-resource

v0.1.0

Published

A resource for event listener/emitter

Readme

npm (scoped) npm NPM npm type definitions coverage AI generation

@xstd/listener-resource

A resource for event listener/emitter

📦 Installation

yarn add @xstd/listener-resource
# or
npm install @xstd/listener-resource --save

📜 Documentation

A ListenerResource is a broadcast hub: values emitted by the source are delivered synchronously, in registration order, to all the registered listeners.

It extends the Resource class from @xstd/resource, so it integrates with the resource lifecycle: closing the resource unregisters all the listeners and rejects any pending consumption.

🏗️ Creating a ListenerResource

The constructor takes an init function, called once, synchronously, with an emit function. Use emit to broadcast a value to all the registered listeners. The init function may return a teardown function, invoked with the close reason when the resource closes.

import { ListenerResource } from '@xstd/listener-resource';

const resource = new ListenerResource<number>((emit) => {
  const interval: ReturnType<typeof setInterval> = setInterval((): void => emit(Date.now()), 1000);
  return (): void => clearInterval(interval); // teardown, invoked with the close reason on close
});

Calling emit after the resource is closed throws.

👂 listen

Registers a listener invoked each time a value is emitted.

  • Mirrors EventTarget.addEventListener semantics: the listener is unregistered when the provided signal aborts.
  • Registering the same listener multiple times registers it multiple times.
  • Registering a listener with an already aborted signal does nothing.
  • The dispatch is fail-fast: when a listener throws, the remaining listeners are not invoked and the error is rethrown to the emitter.
const controller: AbortController = new AbortController();

resource.listen((value: number): void => console.log(value), { signal: controller.signal });

controller.abort(); // the listener is unregistered

Throws if the resource is closed.

⏭️ next

Resolves with the next emitted value.

The returned promise is tied to this resource's lifecycle: it rejects as soon as the provided signal aborts or the resource closes, with the corresponding reason.

const value: number = await resource.next();

🔁 iterator & for await...of

Iterates over the emitted values. ListenerResource also implements Symbol.asyncIterator, enabling for await...of directly over the resource.

Values are buffered according to the queueingPolicy option: with the default EdgeQueuingPolicy, values emitted while the consumer is busy processing the previous one are dropped. The internal listener is unregistered when the iteration ends early (e.g. break), when the provided signal aborts, or when the resource closes.

for await (const value of resource) {
  if (value > LIMIT) break; // the internal listener is unregistered automatically
}

await resource.close();

📚 Full example

import { ListenerResource } from '@xstd/listener-resource';

const resource = new ListenerResource<number>((emit) => {
  const interval: ReturnType<typeof setInterval> = setInterval((): void => emit(Date.now()), 1000);
  return (): void => clearInterval(interval); // teardown, invoked with the close reason on close
});

const controller: AbortController = new AbortController();
resource.listen((value: number): void => console.log(value), { signal: controller.signal });

for await (const value of resource) {
  if (value > LIMIT) break; // the internal listener is unregistered automatically
}

await resource.close();