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

event-worker

v1.3.3

Published

A simpler way of dealing with Web Workers

Downloads

31

Readme

event-worker

Minimalistic event/promified driven web worker abstraction.

Build Status npm version JavaScript Style Guide

Install

npm

npm install event-worker --save

CDN

https://cdn.jsdelivr.net/npm/[email protected]/index.min.js

Usage

Basic example

In your main thread (main.js):

const EventWorker = require('event-worker')

const worker = new EventWorker('path/to/my/worker.js')

async function test(){
  const user = await worker.emit('getUserById', { id: '30242' })

  /*
  {
    id: '30242',
    name: 'neil',
    lastname: 'tyson degrasse'
  }
  */
//...

And then in your web worker (worker.js) you can listen for that event and respond back with the requested data:

const EventWorker = require('event-worker')

const worker = new EventWorker()

worker.on('getUserById', async ({payload}) => {

  let user = await getUser(payload.id)

  return user // Respond back to the main thread with the data requested.

})


async function getUser(id){

  let user = await fetchUserFromLocalDatabase(id)

  if(user) return user

  user = await fetchUserFromServer(id)

  saveUserInLocaDatabase(user)

  return user
}

Workload splitting

If you want to keep your main thread running smoothly dividing the work load of expensive computational task between multiple web workers becomes easier.

From main thread (main.js):

const EventWorker = require('event-worker')

const workerPath = 'path/to/my/worker.js'

const workerPool = [
  new EventWorker(workerPath),
  new EventWorker(workerPath),
  new EventWorker(workerPath)
]

const sum = (a, b) => a + b

const multiplyBy2InOtherThread = (worker, index) => worker.emit('multiply_by_2', index)

(async ()=>
  (await Promise.all(
    workerPool.map(multiplyBy2InOtherThread)
  )).reduce(sum, 0)
)() // 6

From worker (worker.js):


importScripts('path/to/source/event-worker.js')

const worker = new EventWorker()

worker.on('multiply_by_2', ({payload}) => payload * 2 )

Bidirectional communication

You can listen for events triggered by your workers.

From main thread (main.js):

//...

worker.on('interestingData', ({payload})=>{

  doSomethingWithInterestingData(payload)

  return 'Good job worker!'

})

//..

From worker (worker.js):


//...
const res = await worker.emit('interestingData', 'interestingString')

res // => 'Good job worker!!'

Inlining code

Instead of having a separate file for your worker, you can wrap your code inside a function and pass it as an argument to the constructor of EventWorker. This is a good option when prototyping.

From main (main.js):


const worker = new EventWorker(async (mainThread) => {

  let res = await mainThread.emit('sayingHiFromWorker', 'Hi main thread!')

  console.log(res) // Hello worker!

})

worker.on('sayingHiFromWorker', ({payload}) => {

  console.log(payload) // Hi main thread!

  return "Hello worker!"

})

Caveat

When you inline functions it is easy to get confused by the execution context. If you try to access a variable that is outside the scope of the inline function it will fail.


const favoriteAnimal = 'chiguire'

const worker = new EventWorker(async (mainThread) => {
  // This will get executed in a worker.
  mainThread.on('onGetAnimals', ()=>{

    console.log(favoriteAnimal) // fails. favoriteAnimal variable is not in the same execution context.

    //...
  })

})

Error Handling

Error handling works the same as you would expect from a promise executed in the same thread:

From main thread (main.js):

const EventWorker = require('event-worker')

const worker = new EventWorker('path/to/my/worker.js')

worker.emit('rejectThisCall')
  .catch((reason) => {
    console.log(`Rejected because: "${reason}" `)
  })

From worker (worker.js):


importScripts('path/to/source/event-worker.js')

const worker = new EventWorker()

//throwing errors
worker.on('rejectThisCall', () => {
  throw new Error()
})

// throwing async errors
worker.on('rejectThisCallAsync', async ()=> {
  throw new Error()
})

Instead of embedding event-worker into your worker file with a module bundler, you can use the built in function importScripts:


importScripts('path/to/source/event-worker.js')

const worker = new EventWorker()

// ...

EventWorker reference is injected into the global scope once it's loaded.

API

new EventWorker(source) EventWorker

Creates a new instance

  • source string | function | undefined

    • If a string is passed: It will assume it is the worker source file path.

    • If a function is passed it will get converted into a string an then transformed into a worker.

    • If nothing (undefined) is passed it will assume that the environment is the worker.

emit(eventName, data) Promise

Emits a event.

  • eventName String

  • data Any

on(eventName, callback) EventWorker

Registers for an event.

  • eventName

  • callback function(object) => Promise<any>

    Gets executed when eventName is emited.

    • object
      • object.payload any

        Data sent from the event emitter to the listener.

terminate() void

Immediately terminates the Worker. This does not offer the worker an opportunity to finish its operations; it is simply stopped at once.

Changelog

2017-11-04

  • Removed "resolve" and "reject" function properties in the "on" callback.

Contributing

All contributions are welcome.

License

MIT © Alvaro Bernal