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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@vkammerer/postmessage-raf

v0.0.8

Published

A small layer on top of postMessage and requestAnimationFrame to improve performance with web workers

Downloads

4

Readme

A small layer on top of postMessage and requestAnimationFrame to improve performance with web workers.

Installation

npm i @vkammerer/postmessage-raf

Usage

Default mode

In Default mode, the library is nothing more than syntaxic sugar on top of the native postMessage API.

In the main thread:

import { mainMessager } from "@vkammerer/postmessage-raf";

const slaveWorker = new Worker("./slave.js");
const messager = mainMessager({ worker: slaveWorker });

const action = { foo: 'bar' };
messager.post(action);

In "slave.js", the worker:

import { workerMessager } from "@vkammerer/postmessage-raf";

const messager = workerMessager({
  onAction: action => console.log(action.foo); // 'bar'
});

Ping mode  

The point of this library is to optimize the time at which messages are sent between the main and the worker threads, so that every message is exchanged at the beginning of a requestAnimationFrame call.
In order to do that, the worker can call the method startPing on its messager.

In the worker:

messager.startPing();

This triggers the "Ping mode":

  • the main thread will send a "ping" message to the worker on every requestAnimationFrame and the worker thread will respond with a "pong" message.
  • any action posted with messager.post() will not be sent immediately to the other thread, but added to a queue and sent only along with "ping" and "pong" messages.

API

- mainMessager

The function mainMessager takes an single object as parameter, with the following structure:  

const messager = mainMessager({
  worker: new Worker('./slaveWorker.js'),
  // worker instance
  onAction: action => { console.log(`Just received an action of type ${action.type}`) },
  // function to execute on all actions received from the worker
  beforePing: pingCount => {
    console.log(
      `The main thread is about to send a ping.
      The number of pings since startPing was called is ${pingCount}.`;
    )
  },
  afterPing: pingCount => {
    console.log(
      `The main thread just sent a ping.
      The number of pings since startPing was called is ${pingCount}.`;
    )
  }
});

It returns an object with the post method:

const action = {
  foo: 'bar',
  data: ['a', 'b']
}
messager.post(action);
// Sends action to the worker

- workerMessager

The function workerMessager takes an single object as parameter, with the following structure:  

const messager = workerMessager({
  onAction: action => { console.log(`Just received an action of type ${action.type}`) },
  // function to execute on all actions received from the main thread
  beforePong: pongCount => {
    console.log(
      `The worker just received a ping and is about to send a pong.
      The number of pongs since startPing was called is ${pongCount}.`;
    )
  },
  afterPong: pongCount => {
    console.log(
      `The worker just sent a pong.
      The number of pongs since startPing was called is ${pongCount}.`;
    )
  }
  // function executed after the pong message in "Ping mode"
});

It returns an object with the following methods:

post, // Sends action to the worker - see usage here under
startPing, // Initiates "Ping mode"
stopPing, // Terminates "Ping mode" and resumes "Default mode"

Usage:

const action = {
  foo: 'bar',
  data: ['a', 'b']
}
messager.post(action, {
  delay: {
    count: 10,
    // Registers the action to be called at the 10th ping since startPing was called.
    // If the ping has already occured or if the pinging mode is stopped before,
    // the action will be ignored.
    // Not to be used in conjunction with 'index' here under
    index: 12
    // Registers the action to be called 12 pings after the main thread will receive it.
    // If the pinging mode is stopped before, the action will be ignored.
    // Not to be used in conjunction with 'count' here above
  }
});
// Sends action to the main thread

Example diagram

Here under is an example of how a user input U would propagate to the worker application, which could then emit a response R back to the main thread.

mainApp:  -----U-------------------R-----------
pingMsg:  -P-------P-------P-------P-------P---
                   U

pongMsg:  ---P-------P-------P-------P-------P-
                             R
workerApp:-----------U-R-----------------------

As you can see, there is a minimum of two times the duration of requestAnimationFrame calls for the main thread to get a response. If the frame rate is at about 60 FPS, that means we get a response in about 50 ms. This time is satisfying as the user will not notice the latency.

For more information on acceptable latency after user input, see the Response category of the RAIL model.