event-worker

    1.3.3 • Public • Published

    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/event-worker@1.3.0/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

    Install

    npm i event-worker

    DownloadsWeekly Downloads

    27

    Version

    1.3.3

    License

    M.I.T

    Unpacked Size

    12.2 kB

    Total Files

    4

    Last publish

    Collaborators

    • alvarob