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

webworker-async

v1.0.1

Published

Superset of web workers that can export functions to be called as async

Readme

webworker-async

A superset of standard JavaScript web workers with a mechanism to export functions and call them as asynchronous.

// worker.js
import { worker_export } from "webworker-async/worker"

worker_export({
    // a slow way to calculate pi
    expensive_function: () => new Promise(resolve => setTimeout(() => resolve(Math.PI), 1000));
});
// main.js
import { AsyncWorker } from "webworker-async"

let worker_src = new URL("worker.js", import.meta.url);
let worker = AsyncWorker(worker_src, { type: "module" });

let pi = await worker.expensive_function();

worker.terminate();

Async workers extend workers with a super-light asynchronous RPC implementation, which makes worker functions as convenient to use as standard async functions.

Usage

Install from npm:

npm install webworker-async

This package depends on the web-worker npm package, so it's also compatible with Node.js. Generator functions are currently not supported.

Create an AsyncWorker with the same syntax and options as standard workers, plus any functions you want to expose to it (but without the new keyword).

You can use async workers exactly like standard web-worker workers by not importing or exporting functions, and they will provide extra type safety and parameter documentation. This use-case is supported from typescript with AsyncWorker<{}>.

Exporting and calling worker functions

Workers can expose functions to their owners via the provided worker_export function. The export function may be called multiple types, but will exports with the same name will be overwritten. Exports with the names of standard worker properties (terminate, addEventListener, ...) will not be callable, as those properties are still accessible from the worker object.

Worker functions may be called with any value supported by the structured clone algorithm (meaning functions and symbols, among some others, cannot be passed as arguments to exposed functions).

When called from the worker's owner, the function will return a Promise exactly like a regular asynchronous function. The promise will reject if the function is not defined or throws an error from the worker.

// calculating pi concurrently with a fallback approximation 
// (not a very good one, remember calculating pi is expensive!)
let pi_label = "loading π...";

worker.expensive_function()
    .then((result) => pi_label = `π = ${result}`)
    .catch(() => pi_label = "π ≈ 3.2");

Exposing functions to workers

For full bi-directional communication, workers may be exposed to a set of functions to call from the owner. These are passed alongside the worker options at creation time, but the object may be extended afterwards. these functions will be available from the worker via the worker_import function.

import { AsyncWorker } from "webworker-async"
const worker_src = new URL(/* ... */);

const events = [];

const worker = AsyncWorker(worker_src, { type: "module", imports: {
    append_event: (data) => events.push(data);    
}});
// worker.js, now with imports!
import { worker_import } from "webworker-async/worker"

const { append_event } = worker_import();

append_event({ type: "test", message: "hello world" })
    .catch(error => console.error("Something went wrong"));

Type safety

When called from typescript, AsyncWorker and worker_import are optionally generic over the exposed functions. They will automatically wrap the provided functions to be asynchronous.

Additionally, worker_export will return the object passed to it as a convenient way to export its type. Below is an example of these techniques used to achieve type safety:

// calculator.worker.ts
export type Calculator = typeof exports;

const exports = worker_export({
    add: (a: number, b: number) => a + b,
    subtract: (a: number, b: number) => a - b, 
});
// main.ts
import type { Calculator } from "./calculator.worker"
let worker = AsyncWorker<Calculator>(/* ... */);

// worker now has autocomplete for add and subtract as well as the standard worker properties, and nothing else!

Abstraction leaks

Async workers are fully compatible with standard workers, including the ability to simultaneously use the standard messages and events if ever required.

To ensure your additional event listeners don't respond to worker function events (or to extend specifically worker function calls), you can use the provided is_async_event helper.

// worker.js with exported function and extended functionality
import { worker_export, is_async_message } from "webworker-async/worker";

worker_export({ fn: () => {} });

addEventListener("message", (event) => {
    if(is_async_event(event)) {
        // Log any calls to exported functions
        if(event.data.type === "call") {
            console.debug(`Main thread called ${event.data.function_name}`);
        }
    } else {
        // Echo any non-async messages
        postMessage(event.data);
    }
});