3 JS ES6 PubSub Summary

1. JavaScript ES6 PubSub

I write the by referring redux store, store could be global, component-base or inside a namespace.

const PubSub = {

    callbacks: {},

    subscribe(ch, callback) {
        const calls = this.callbacks;
        callback = callback || this.render;
        (calls[ch] || (calls[ch] = [])).push(callback);

        return () => {
            delete calls[ch];
            return calls;
        }
    },

    publish() { //dispatch
        let args = [].slice.call(arguments, 0);
        let ch = args.shift();

        if (!this.callbacks || !this.callbacks[ch]) {
            throw new Error(ch + ' not exist');
            return this;
        }

        // dispatch to update redux store. cb==render
        this.callbacks[ch].forEach(cb => cb(args));

        return this;
    },

    render () {
        console.log('PubSub default callback')
    }
}

PubSub.subscribe('channel1', () => console.log('callback 1'));
PubSub.subscribe('channel2', (val) => console.log('callback 2: ' + val));
PubSub.subscribe('channel3', (ary) => console.log('callback 3', ary));

PubSub.publish('channel1');  //callback 1
PubSub.publish('channel2', 123);  //callback 2: 123
PubSub.publish('channel3', [1, 2, 3]); //callback 3 [1, 2, 3]

const unsubscribe = PubSub.subscribe('channel6');
unsubscribe();

PubSub.publish('channel4', [1, 2, 3]); //callback 3 [1, 2, 3]

2. JavaScript ES6 functional createStore

function ManageStore(reducer) {
    this.state = null;
    this.listeners = [];
    this.reducer = reducer || this.reducerAction;

    //TODO: settings;
    console.log(ManageStore == this, ManageStore === this);

    this.dispatch({});
}

ManageStore.prototype = {

    getState () {
        return this.state;
    },

    dispatch (action) {
        this.state = this.reducer(this.state, action);
        this.listeners.forEach(listener => listener())
    },

    subscribe(listener) {
        this.listeners.push(listener);
        return () => {
            this.listeners = this.listeners.filter(l => l !== listener)
        }
    },

    reducerAction (state, action) {
        return this.state;
    }
};

ManageStore.prototype.constructor = ManageStore;

ManageStore.state = {};

let store = new ManageStore();
store.state === ManageStore.state; //false

3. JavaScript ES6 jQuery version PubSub

//https://github.com/cowboy/jquery-tiny-pubsub/blob/master/src/tiny-pubsub.js
(function ($) {

    const o = $({});

    $.subscribe = () => o.on.apply(o, arguments);

    $.unsubscribe = () => o.off.apply(o, arguments);

    $.publish = () => o.trigger.apply(o, arguments);

}(jQuery));

my React-Redux-Fullstack app in github

my React-Redux-Fullstack app in github

I add some screenshots in README.md, so it is more meaningful and readable:

https://github.com/jxjwilliam/react-redux-fullstack

It is an app integrated with:

1. Front-end

react, redux, react-route-dom, redux-middleware, socket.io-client, rxjs, isomorphic-fetch, superagent, redux-form, flexbox, media-objects, scss, bootstrap, font-awesome, react-bootstrap, smoothie

2. Server-side

express, mongodb, postgresql, socket.io, redis, rabbitmq, request, data-schema, routes, cors

3. Support servers/tools

– mongod server /robomongo
– postgresql server / pgadmin
– redis server
– rabbitmq server
– git
Without them also work, but some functionality and features will not show.

4. Others

webpack, babel, karma, mocha, chai, webpack-dev-middleware, webpack-hot-middleware, *-loader, redux-devtools-extension, faker, moment, lodash, node-uuid, prettyjson, jsonwebtoken, web-dev-server

In one word, it works fine, is a good start to digger more details.

JavaScript ES5 and ES6 setTimeout

JavaScript: ES5, ES6 setTimeout

Are the 2 following closures same?

// closure
for(var i=1; i<6; i++) {
  setTimeout((function(i) {
    return function() {
      console.log(i);
    }
  }(i)), 1000)
}

for(var i=1; i<6; i++) {   
  setTimeout( ((n) => () => console.log(n))(i), 1000)
}

Are the following 2 IIFE same?


for(var i=1; i<6; i++) {
  (function(i) {
    setTimeout(function() {
      console.log(i)
    }, 1000)
  })(i)
}

for(var i=1; i<6; i++) { 
  ((i) => setTimeout(() => console.log(i), 1000))(i)
}

the first use closure, the second IIFE.

3 Observer Pattern implementations

3 Observer Pattern implementations

I extract The Observer pattern from https://en.wikipedia.org/wiki/Observer_pattern:

There is a helpful article for this:

Comparison between different Observer Pattern implementations

1. Event Emitter/Target/Dispatcher

myObject.addEventListener('myCustomEventTypeString', handler);
myObject.dispatchEvent(new Event('myCustomEventTypeString'));
myObject.removeEventListener('myCustomEventTypeString', handler);

2.Publish / Subscribe (pub/sub)

globalBroadcaster.subscribe('myCustomEventTypeString', handler);
globalBroadcaster.publish('myCustomEventTypeString', param1, param2, ...);
globalBroadcaster.unsubscribe('myCustomEventTypeString', handler);

3. Signals

myObject.myCustomEventType.add(handler);
myObject.myCustomEventType.dispatch(param1, param2, ...);
myObject.myCustomEventType.remove(handler);

Tiny Publish-Subscribe implementation in jQuery

Tiny Publish-Subscribe implementation in jQuery

Very helpful article: jQuery Tiny Pub/Sub: A really, really, REALLY tiny pub/sub implementation for jQuery.

(function($) {
  var o         = $({});
  $.subscribe   = o.on.bind(o);
  $.unsubscribe = o.off.bind(o);
  $.publish     = o.trigger.bind(o);
}(jQuery));

The $.subscribe, $.unsubscribe and $.publish methods all use the jQuery .on(), .off() and .trigger() methods internally.

Just use this handy terminology guide (jQuery events term → Pub/Sub term), and everything should make sense:

  • on → subscribe
  • off → unsubscribe
  • trigger → publish
  • type → topic

More examples:


function handle(e, a, b, c) {
  // `e` is the event object, you probably don't care about it.
  console.log(a + b + c);
};

$.subscribe("/some/topic", handle);

$.publish("/some/topic", [ "a", "b", "c" ]);
// logs: abc

$.unsubscribe("/some/topic", handle); // Unsubscribe just this handler

// Or:

$.subscribe("/some/topic", function(e, a, b, c) {
  console.log(a + b + c);
});

$.publish("/some/topic", [ "a", "b", "c" ]);
// logs: abc

$.unsubscribe("/some/topic"); // Unsubscribe all handlers for this topic

github: React Redux Full Stack

github: React-Redux-FullStack

I build a `React-Redux-FullStack` app from scratch. Besides `main` branch, there are also other 9 branches which mark the different increment steps. Pretty cool stuff.

https://github.com/jxjwilliam/react-redux-fullstack

It includes a lot of stuff, a total full-stack implementation, which include react, redux, middlewares, express, mongodb, promise, unit tests, ES6 & Babel & Webpack, Restful APIs, fake-data on the fly, etc. For details, visit https://github.com/jxjwilliam/react-redux-fullstack.

It is easy to start:

$ git clone https://github.com/jxjwilliam/react-redux-fullstack.git
$ npm install
$ npm run dev
$ open http://localhost:8081

Mongodb needs to be installed and running while start the app. An excellent tool `robomongo` can be used to monitor MongoDB data.

github: React-Redux-TodoList

github: React-Redux-TodoList

While watch `Dan Abramov` Redux tutorial videos, I built a `React-Redux-TodoList` app from scratch.

https://github.com/WilliamJiang/Getting-Started-with-Redux

The app follows Dan Abramov’s video tutorials to implement TodoList step by step, very helpful. I also add some good-stuff, like:
– fully redux-react implementation with action/reducer/connect-binding.
– ES6, babel, webpack
– ReactiveX programming: redux-rxjs.
– userList tables: sorting, pagination, add record, delete record, promise access etc…
– dynamic faker-data on the fly.
– Full implementation of todoList.
Besides `main` branch, there are also other 10 branches which mark the different increment steps.

It is easy to start:

$ git clone https://github.com/WilliamJiang/Getting-Started-with-Redux.git
$ npm install
$ webpack-dev-server
$ open http://localhost:8080

It is like a startup boilerplate, you can copy TodoApp.js, or step-7.js and paste to `jsbin` to practise, or add more stuff like thunk, redux-form, bootstrap-stuff, rxjs, react-redux-npm-modules for different purposes.

To use it, update webpack.config.js’ entry, change entry point to `step-8.js`, or `step-9.js` or `TodoApp.js`, to practise different React-Redux demo. This is a clean-way to focus on some certain point; then later organize them together.

Use Object.assign to replace Redux isomorphic object

Use Object.assign to replace Redux isomorphic object

let state = {
  stars: 5,
  list: [1,2,3,4,5],
  comment: { user: 'weber', note: 'cyberspace' }
}

//1. replace scalar variable:
var s1 = Object.assign({}, state, { stars: 8 });
console.info('1: ', JSON.stringify(state), JSON.stringify(s1));

//2. replace array:
var s2 = Object.assign({}, state, { list: state.list.slice(2) });
console.info('2: ', JSON.stringify(state), JSON.stringify(s2));

// 3. replace object:
var comment = state.comment
var s3 = Object.assign({}, state, {
  comment: {
    user: 'what-ever-user',
    note: comment.note
  }
});
console.info('3: ', JSON.stringify(state), JSON.stringify(s3));

In every case, the original state keeps unchanged, and new generated object is updated, which is as expected.