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

wtfork

v0.3.0

Published

Subscribe to and publish events between parent and child node processes using the standard node event emitter api or call parent methods directly from the child process and vice versa.

Downloads

8

Readme

What the Fork

Downloads Downloads npm version dependencies dev dependencies License

Subscribe to and publish events between parent and child node processes using the standard node event emitter api or call parent methods directly from the child process and vice versa.

See the example in /example for full usage.

Getting Started

Install it via npm:

npm install wtfork --save

IPC via Event Emitter

You can subscribe to and publish events between parent and child node processes using the standard node event emitter api.

Instead of:

process.on('message', function (msg) {
  if (msg && msg.isThisTheMessageForMe) {
    // ok i want this message
  }
});

You can simply do the following in your child process:

// can also be .once()
process.parent.on('thisIsTheMessageForMe', function (data) {
  console.log(data);
});

Example:

Parent process:

import { fork } from 'wtfork';

// create a forked process as normal using standard node fork api
const myDispatcherProcess = fork('./path/to/child.js', [], {});

// subscribe to the child's `hello` event
// can also be .once()
myDispatcherProcess.child.on('hello', function (data) {
  console.log(`I am the parent and I received data for child event 'hello': ${JSON.stringify(data)}`);
  // send a `helloBackAtYou` event to the child process
  myDispatcherProcess.child.send('helloBackAtYou', { bar: 'foo' });
});

Child process:

// you don't need to require wtfork on the child, it will automatically be required

// subscribe the the `helloBackAtYou` event to be received from the parent
// can also be .once()
process.parent.on('helloBackAtYou', function (data) {
  console.log(`I am the child and I received data for parent event 'helloBackAtYou': ${JSON.stringify(data)}`);
});

// send a `hello` event to the parent process
process.parent.send('hello', { foo: 'bar' });

IPC via Method Calls

This allows you to setup some methods on the parent and child processes that can be called from either process.

Each method MUST return a promise (but only if you want to receive data back)

The fork method accepts the same arguments as node's fork but with an optional 4th argument of methods.

The method argument accepts a class instance or an object with methods. Any methods found here are then available to the child to remotely call via process.parent.methods.someCoolMethod(...args).

Note: constructor methods and private methods (beginning with _) are automatically excluded.

To make child methods available to the parent you need to module export using the standard modules syntax for node. See the child example below.

Optionally you can also call process.parent.setChildMethods(classOrObjectOfMethods) on the child, this however will replace all methods created via module exports

Example:

Parent process:

import { fork } from 'wtfork';
/*
 Some random class of methods you might want to IPC method call
 Doesn't have to be a class, can also be an object with methods
 */
class Test {
  /**
   *
   * @param str
   * @returns {Promise}
   */
  hello(str) {
    return new Promise((resolve) => {
      console.log(`Im a parent method called 'hello' and I just ran: ${str}`);
      return resolve({ some: 'data' });
    });
  }

  /**
   *
   * @param str
   * @param something
   * @returns {Promise}
   */
  goodbye(str, something) {
    return new Promise((resolve, reject) => {
      console.log(`Im a parent method called 'goodbye' and I just ran: ${str} - ${something}`);
      return reject(new Error('Please don\'t leave me!'));
    });
  }

  /**
   * Some private method - private methods are excluded by default
   * @param secrets
   * @private
   */
  _somePrivateMethod(secrets) {
    return new Promise((resolve) => {
      console.log('You can\'t see me child process.');
      return resolve(secrets);
    });
  }
}

// create a forked process as normal using standard node fork api
// but with an additional 4th param of a class or object containing methods
const myDispatcherProcess = fork('./example/child', [], {}, new Test());

// subscribe to the child's `helloBackAtYou` event
myDispatcherProcess.child.on('helloBackAtYou', (data) => {
  console.log(`I am the parent and I received data for a child event 'helloBackAtYou': ${JSON.stringify(data)}`);

  // lets call the child processes hello method - it should always resolve with no error
  myDispatcherProcess.child.methods.simples('meerkat').then((result) => {
    console.log(`The child method 'simples' resolved back to the parent with: ${JSON.stringify(result)}`);
    // now quit maybe?
    myDispatcherProcess.child.methods.quit(0); // doesn't need to be a promise
  }).catch((error) => {
    console.error('The child method \'simples\' errored back to the parent.');
    console.error(error);
  });
});

// send a hello event to the child, the child in turn responds with a helloBackAtYou event.
myDispatcherProcess.child.send('hello', { bar: 'foo' });

Child process:

// just export as you would any other module to setup available child methods

// or module.exports.simples = function( ...
// or export default function simples(...
// or export default { ...object with methods }
// or export default new MyChildHelperClass();
module.exports = {
  /**
   * Just resolves with the same value, simples!
   * @param someVal
   * @returns {Promise}
   */
  simples(someVal) {
    return new Promise((resolve) => {
      console.log(`Im a child method called 'simples' and I just ran: ${someVal}`);
      return resolve(someVal);
    });
  },

	/**
   * Unnecessary function to quit because we can
   * @param code
   */
  quit(code) {
    console.log('Child process will now exit as instructed by parent...');
    process.exit(code);
  },
};

// subscribe the the `hello` event to be received from the parent
process.parent.on('hello', function (data) {
  console.log(`I am the child and I received data for parent event 'hello': ${JSON.stringify(data)}`);
  // send a `helloBackAtYou` event to the parent process
  process.parent.send('helloBackAtYou', { foo: 'bar' });
});

// lets call the parent processes hello method - it should always resolve with no error
process.parent.methods.hello('test string').then((result) => {
  console.log(`The parent method 'hello' resolved back to the child with: ${JSON.stringify(result)}`);
}).catch((error) => {
  console.error('The parent method \'hello\' errored back to the child.');
  console.error(error);
});

// lets call the parent processes goodbye method - it should always error
process.parent.methods.goodbye('test string', 'wtfork').then((result) => {
  console.log(`The parent method 'goodbye' resolved back to the child with: ${result}`);
}).catch((error) => {
  console.error('The parent method \'goodbye\' errored back to the child:');
  console.error(error);
});

Running the parent in this example will produce the following output:

Im a parent method called 'hello' and I just ran: test string
Im a parent method called 'goodbye' and I just ran: test string - wtfork
I am the child and I received data for parent event 'hello': {"bar":"foo"}
The parent method 'hello' resolved back to the child with: {"some":"data"}
I am the parent and I received data for a child event 'helloBackAtYou': {"foo":"bar"}
Im a child method called 'simples' and I just ran: meerkat
The child method 'simples' resolved back to the parent with: "meerkat"
Child process will now exit as instructed by parent...
The parent method 'goodbye' errored back to the child:
Error: Please don't leave me!
    at parent.js:29:21
    at new Promise (/Users/Mike/Documents/Personal/Projects/wtfork/node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:193:7)
    at Test.goodbye (parent.js:27:12)
    at EventEmitter.<anonymous> (index.js:243:89)
    at emitOne (events.js:90:13)
    at EventEmitter.emit (events.js:182:7)
    at ChildProcess.<anonymous> (index.js:199:26)
    at emitTwo (events.js:100:13)
    at ChildProcess.emit (events.js:185:7)
    at handleMessage (internal/child_process.js:718:10)

Process finished with exit code 0

A simpler child process could be written as:

import MyChildHelperClassOfDoom from './childThingyClassStuff';
export default new MyChildHelperClassOfDoom();

// and then on the parent you can just call all the methods available to MyChildHelperClassOfDoom
// so you don't really need to use events this way but they're there if you need them.

// just 2 lines - simples right? \o/

Notes:

  • Each method call is given a unique id when called to allow multiple calls of the same methods simultaneously without event naming conflicts, this uses the cuid npm module to produce colission resistant ids.
  • Each child process is also given it's own unique id using cuid. Internally this isn't used that much except for event source verification, however, in terms of tracking child processes without knowing a PID then this is useful - the id can be found at process.parent.child_id on the child and on the parent it can be found at yourForkedProcess.child.id
  • Until the child confirms it's ready any child method calls or events sent from the parent will be buffered and sent once ready.

License

MIT