courierjs
v1.0.0
Published
A simple event manager with middleware
Downloads
2
Maintainers
Readme
CourierJS
A simple event messenger that allows you to apply some middleware before the message is received by the listener.
Inspired by Flux and Redux.
About
CourierJS is designed to be a simple message receiver and dispatcher, with the option of applying middleware to the data passed to an event and passing that processed data to the listeners.
The concept was inspired by learning how Flux and Redux works. Redux uses the store to subscribe and publish action messages, with the reducer sitting in the middle as a processor that takes the action message and generates a new state for the component.
In CourierJS, the messenger works as your store, brokering messages from publishers to subscribers, and the middleware functions as your reducer, with the benefit of being able to break your reducer up into distinct steps. This allows a more functional approach as the focus is on functions generating your new state as opposed to storing and mutating state.
Installation
You can install CourierJS by running the following:
$ npm install --save courierjs
Importing
You can include CourierJS by doing the following
// ES6 imports
import Courier from 'courierjs';
// or...
// standard node require()
var Courier = require('courierjs').default;
Usage
To use CourierJS, you need to instantiate the messenger object.
let messenger = new Courier();
The subscribe()
function takes an event identifier string, and a callback
function which will be called when a message with that identifier is received.
The subscribe callback takes one argument, data which is either the data object
passed to the publish()
method, or the result returned by applying the middleware
to the data object passed to the publish()
method.
messenger.subscribe('message-id', (data) => {
console.log(data);
});
The publish()
function allows you to send a message and data to all available
subscribers.
messenger.publish('message-id', {
someVal: 'hello world',
someOtherVal: 'this is a test'
});
Sometimes, you no longer need subscribers to listen for a message, in this case
you can use clear()
to remove all subscribers to a particular message id.
messenger.clear('message-id');
// messenger.listeners['message-id'].length === 0
Middleware can be registered to a particular message id by using the register()
function. The register function takes the message id it will be applied to as the
first param and an applicator function as the second param.
The applicator function takes two parameters, the first being the data passed to
it, the second being the continuation function. The next()
function takes 1
parameter, which is the value to pass as the first parameter to the next
middleware function, or, the data to be passed to the subscribed listeners.
let courier = new Courier();
courier.subscribe('test', function (data) {
expect(data.val).to.eql(3);
});
courier.register('test', function (data, next) {
data.val += 1;
return next(data);
});
courier.register('test', function (data, next) {
data.val += 1;
return next(data);
});
courier.register('test', function (data, next) {
data.val += 1;
return next(data);
});
courier.publish('test', { val: 0 });
ReactJS Example
The following is an example of using CourierJS in React, the middleware (similar to a reducer in Flux/Redux) takes in the message via the message id, and receives the data passed to it from the message sender.
The middleware applicator function receives the data, which in this example is a configuration object for jQuery's ajax implementation and returns the promise generated by jQuery.
Since this is the only applicator function in the chain, the value returned by the function is then passed to the message receiver. The message receiver then assigns a promise-resolution callback within it's context so the returned result from the promise can be handled in the component context.
Refer to example/
for the associated code.
App.js
import * as React from 'react';
import AppChild from './AppChild';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
apiResponse: ""
};
// tell CourierJS that the message handler is here
this.props.messenger.subscribe('fetch-api', this.onReceiveAPIPromise.bind(this));
}
// because we have moved to a continuation based middleware passing style
// we can have the deferred resolve method be the call which passes data
// to the subscribers
onReceiveAPIPromise(data) {
// get the resolved promise and update state
let newState = Object.assign(this.state, {
apiResponse: JSON.stringify(data)
});
this.setState(newState);
}
render() {
return (
<div>
<h1>CourierJS ReactJS Example</h1>
<AppChild messenger={this.props.messenger} />
<pre>{this.state.apiResponse}</pre>
</div>
);
}
}
AppChild.js
import * as React from 'react';
export default class AppChild extends React.Component {
onButtonClick() {
// when the button is clicked, send fetch-api message
this.props.messenger.publish('fetch-api', {
url: 'https://jsonplaceholder.typicode.com/posts',
method: 'GET'
});
}
render() {
return (
<div>
<h3>Click below</h3>
<button onClick={this.onButtonClick.bind(this)}>Click to spawn jQuery request</button>
</div>
);
}
}
index.js
import Courier from 'courierjs';
import jQuery from 'jquery';
import * as React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
// create CourierJS instance and register middleware
let messenger = new Courier();
messenger.register('fetch-api', function (data, next) {
jQuery.ajax(data).then(next);
});
ReactDOM.render(
<App messenger={messenger} />,
document.getElementById('root')
);
Possible Patches
- have
subscribe()
andregister()
return a unique ID that can be used to remove individual middle applicators or message receivers
License
This software is licensed under the MIT license. Refer to LICENSE
for details.