JavaScript Constructor Pattern

There are 3 ways to create an object in JavaScript:

let object1 = {};

let object2 = Object.create(Object.prototype);

let object3 = new Object({key: val, ... });  

The first option is an object literal where basically is a key-value pair.

The second lets you specify the prototype for the object you're trying to create. You'll able to see it by accessing object2.__proto__. You'll need to specify the prototype or otherwise it will throws.

Remember that every object inherits Object.prototype by default.

So for instance, object1.__proto__ will be equivalent to Object.prototype without be obliged to specify the prototype by yourself. But for the second option, you'll be needing to sepcify Object.prototype by yourself.

The following achieve the same result as the third option:

Object({key: val, ... });  
Accessing and Mutating Props

You'll mainly use either dot notation . or a bracket notation [].

For setting/assigning a new property, you can also use Object.defineProperty(), by the following syntax:

Object.defineProperty(obj, prop, descriptor)  

There are two type of descriptor, you can only choose either of these, otherwise it will throws.

  • data descriptor
  • accessor descriptor

Both have the following key:

  • configurable: are the descriptor mutable?
  • enumerable: will the property shows up during enumeration (for ... in and Object.keys).

For data descriptor:

  • value: well, the value for the property.
  • writable: is the property mutable?

Ex:

Object.defineProperty(obj, 'awesomeKey', {  
  enumerable: false,
  configurable: false,
  writable: false,
  value: 'Some random awesome value'
});

There are defaults for every of these descriptor keys, so you don't have to explicitly specify for each.

But if you don't, there is a possibility where the options are inherited from the prototype chain. I'm not really sure about this, though...

For accessor:

  • get
  • set

Both get and set are function that will be executed when you either assign or access the corresponding key. For instance:

let Cat = {};  
Object.defineProperty(Cat, 'age', {  
    get: function() {
      return this.age || 10;
    },
    set: function(value) {
      this.age = value;
    }
  });

console.log(Cat.age); // returns 10  
Cat.age = 12;  
console.log(Cat.age); //returns 12  

Why Redux Use Pure Function

Before going straight to the question, let us steal a piece of code from Redux that features combineReducers() function.

It seems that my previous understanding on how Redux implements combineReducers() does not aligns with the current implementation.

Here's my prior understanding on how it works:

const combineReducers = (reducers) => {  
  return (state = {}, action) => {
    return Object.keys(reducers).reduce(
     (nextState, key) => {
       nextState[key] = reducers[key](
         state[key],
         action,
       );
       return nextState;
     },
     {});
  }
}

Current Implementation:

var reducerKeys = Object.keys(reducers);  
var finalReducers = {};  
for (var i = 0; i < reducerKeys.length; i++) {  
  var key = reducerKeys[i];
  finalReducers[key] = reducers[key];
}
var finalReducerKeys = Object.keys(finalReducers);

return function combination() {  
    var state = arguments[0];
    var action = arguments[1];

    var hasChanged = false;
    var nextState = {};
    for (var i = 0; i < finalReducerKeys.length; i++) {
      var key = finalReducerKeys[i];
      var reducer = finalReducers[key];
      var previousStateForKey = state[key];
      var nextStateForKey = reducer(previousStateForKey, action);
      if (typeof nextStateForKey === 'undefined') {
        var errorMessage = getUndefinedStateErrorMessage(key, action);
        throw new Error(errorMessage);
      }
      nextState[key] = nextStateForKey;
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
    }
    return hasChanged ? nextState : state;
  };

Note: several lines of code are stripped for simplicity sake.

As you can see it is no longer using the reduce() as it was.

It is making certain optimization by considering whether the new state of the corresponding reducer has changed.

If one of the state changes, then it will return the whole new state. Otherwise if none changes ( nextStateForKey !== previousStateForKey keeps returning false ), it will return the previous state, and I assume there won't be any re-rendering.

Redux does this to ensure efficiency. Why re-renders if the state is equivalent as it was.

Due it's deterministic behavior, it will outputs the same result with the same input.

This leads to the question...

Why Pure Function?

As you saw in the preceding code, the combination() determines whether returning a new state is necessary through === operator, which is far efficient than a deep comparison.

Making any mutation to a state (and returning the mutated state) will make the comparison (hasChanged) results to false, which is not something we want to have (because a change HAS occur!).

Now.

One of the characteristic of pure function is it's prohibition to
mutate the arguments the function receives.

It matches exactly on how a reducer needs to be designed!

Every time a changes is made upon a state, a reducer has to return a new fresh state, and NOT making changes to the argument (previous state), therefore making it easier for Redux to tell whether it a change has occur.

It's that simple.

Encoding in 250 words

Computer speak in 1 and 0 (ones and zeroes), commonly referred to as binaries.

To produce character like A, 3, or ø it needs to know how to map each of those letters to binaries. Same situation applies when computer want to interpret data from binaries.

It may interpret a byte of 01000001 as A or perhaps B, depends on who sets up the rule in the first place.

Encoding basically a set of rule on mapping letters to binaries, and vice versa.

Know that a sequence of binary can be converted into to number (base 10) or hexadecimal (base 16). So keep it mind that a byte of 01000001 is equivalent to 65, and equivalent to 0x41 (0x indicates the that it’s a hex).

ASCII

One of the earliest encoding known is ASCII/ANSI.

They map decimal values from 0 to 127 to Western alphabets and control codes (tab, escape, backspace, etc) .

Mapping numerical values from 0-127 only takes up 7 bit of space. It does not specify numerical values from 128 to 255. So basically it wastes a bit for every byte. And it does not define characters for the rest of the world.

Unicode

Unicode isn’t necessarily an encoding but it does provide an interesting idea about code points.

All characters in the whole world is mapped to a form of U+WXYZ, whereas W, X, Y, and Z, are all hexadecimal values, which are able to hold numerical values 0-65535.

Now, there are several encoding to map this code points to real binaries:

  • UTF-7

  • UTF-8

  • UTF-16

  • UTF-32

Further readings:

Related concepts:

Using Redux Saga To Manage Your Side Effects

If you’re using Redux anytime by now, you’ll realize as your codebase goes large, so does your side effects. And by side effects I mean data fetching, or any async processes that needs special treatment.

Previously people would suggest to use redux-thunk, which basically is an action creator that returns a function, in which it will be invoked in your middleware. But it has it’s own challenges:

  • it’s not testable
  • no concurrency
  • the bigger the codebase, the more complicated it will be

Having Redux Saga as one of your dependency will tremendously makes life much easier as it abstracts complex async operation beneath the library’s core.

There are several prerequisite before proceeding to look for Redux Saga, you need to understand about generators and promises, better yet, async-await style.

This is because Redux Saga uses generators. Implementing a saga requires you to keep yielding stuff.

I suggest you to read the following beforehand:

Introduction

Redux Saga === Middleware

Yup, Redux Saga is just another kind of middleware that will intercept any of your dispatched action before handing it over to your reducer.

Getting Started

Because it’s a middleware, you need to specify your saga when creating your Redux store.

import {  
  createStore,
  applyMiddleware,
} from 'redux'
import createSagaMiddleware from 'redux-saga'  
import reducer from './reducers'  
import mySaga from './sagas'

// create the saga middleware
const sagaMiddleware = createSagaMiddleware()  
// mount it on the Store
const store = createStore( reducer, applyMiddleware(sagaMiddleware) )  
// then run the saga
sagaMiddleware.run(mySaga)  

This code is taken from the official documentation.

Watcher and Worker Saga

Generally you’ll have two kinds of saga:

  • Watcher Saga

  • Worker Saga

Watcher Saga watches for any incoming dispatched action.

When it receives one, it will spawns/initiate a worker saga, often referred to as a task, which will do the work.

I like to think a task as just another layer of middleware, but with a special ability of pausing and resuming.

Therefore, you can initiate multiple of worker saga/tasks at the same time, each will work concurrently.

Effects

You’ll see from the preceding code there’s a magic call  and put  invocation. call *and *put doesn’t directly invoke a function that does the work, instead it returns an instruction for the middleware to execute.

Here’s what it looks like:

{
  CALL: {
    fn: Api.fetch,
    args: ['./products']
  }
}

This kind of pattern is seen in a lot of libraries, including React’s React.createElement().

Redux Saga call this as an effect.

Call and put is two of several other effects Redux Saga introduces, but frankly you won’t need all.

Combining it all

Here’s what a typical watcher and worker saga would look like:

// defining your watcher saga
function* watcherSaga() {  
  yield takeLatest('FETCH_ALL_USERS_DATA', workerSaga);
}
// defining your worker saga
function* workerSaga(action) {  
  yield fetchResult = call(httpRequest);
  yield put({
    type: 'FETCH_RECEIVED',
    payload: fetchResult,
  });
}

Take a closer look on mySaga from the previous chunk of code, and that will be your saga’s starting point.

You’ll generally will always start with a watcher saga, it means that mySaga will be a watcher saga.

On this sagaMiddleware.run(mySaga) line of code, Redux Saga will directly runs your mySaga.

And what mySaga will generates is an instruction for the middleware!

So from the previous example, takeLatest will generate an instruction.

What does this instruction says?

It says to wait for the latest dispatched action FETCH_ALL_USERS_DATA, and when that action is dispatched, initiate the specified worker saga.

You can build your watcher saga like this:

function* watcherSaga() {  
  yield takeLatest('ACTION_A', workerSagaA);
  yield takeLatest('ACTION_B', workerSagaB);...and so on
}

Redux Saga flow on sagaMiddleware.run(watcherSaga) call:

  1. watcherSaga is called.

  2. watcherSaga will returns an instruction for ACTION_A.

  3. middleware receive the instruction then continues to run watcherSaga.

  4. watcherSaga returns another instruction for ACTION_B.

  5. middleware receives the instruction then continues to run watcherSaga.

This whole process will stop whenever a blocking effect is reached, commonly known blocking effects are:

  • call

  • take

Call returns an instruction to the middleware to call the given function (which has to return a promise). The middleware will wait until the promise resolves and then continue to run the saga.

Take returns an instruction to the middleware to wait for a specific action before proceeding the saga.

What I was just elaborating what happens when sagaMiddleware.run(watcherSaga) is called, which in essence, just to provide as many instruction to the middleware.

You can deep more in the official documentation here: http://yelouafi.github.io/redux-saga/

Or even try yourself the library which you can find here: https://github.com/yelouafi/redux-saga

Dissecting Redux (Part 3)

middleware implementation

Middleware sounds fancy, but it does nothing rather than wrapping your store.dispatch() function. The idea is to intercept your action before it reaches the original .dispatch() function.

So, how would you wrap it?

Well, it’s fairly simple.

You probably familiar with this pattern:

let a = 'string';  
let saveA = a;  
a = 'another string';</code>  

Instead of string, it saves the original store.dispatch() to a temporary variable, then assigns the store’s dispatch property to another function (middleware).

We might look it like:

let store = createStore();  
let originalDispatch = store.dispatch;  
let middleware = (action) => { //some awesome things to do here originalDispatch(action); } store.dispatch = middleware;  

When we’re up to dispatch an action, we end up invoking the middleware first.

The built-in middleware by Redux is way more robust than this one, but I assume it’s pretty clear from here, yes?

Now, what if we want to build several middlewares? We probably will have to reassign store.dispatch a couple times.

What if we want more and more middlewares? Our current approach is no longer reliable.

We need a better solution.

So here comes Dan’s approach, he built a function that performs the preceding block of code.

const wrapDispatchWithMiddlewares = (store, middlewares) => {  
  middlewares.slice().reverse().forEach((middleware) => {
    store.dispatch = middleware(store)(store.dispatch);
  })
}

Let’s take this on slowly.

Keep in mind that we need to inject a store and middleware to this function.

const store = createStore();  
const middlewares = [promise, logging]; // promise & logging is a function  
wrapDispatchWithMiddlewares(store, middlewares);  

Now, let’s analyze this bit of code: middlewares.slice().reverse().

He wants to slice() and reverse() for the sake of making promise middleware being the outermost middleware.

Slicing is done to prevent mutating the original array due to reverse().

You see, previously we set an array of middlewares, and as the list goes the array would become like:

[promise, logging, mw3, mw4, mw5, …].

It’s not so much of a big deal though, but the idea is to keep promise function to be the outermost (last evaluated).

For the next bits:

.forEach((middleware) => {
  store.dispatch = middleware(store)(store.dispatch);
})

Remember that the interpreter will evaluate this middleware(store)(store.dispatch) first.

Not to forgot what our middleware will look like, Dan come up with this functional form:

let middleware = (store) => (next) => (action) => {}  

This is called currying.

Basically, you just looping over: returning a function and calling it again.

The last function would then be able to access the store and next variable, thanks to closure.

Keep in mind that the middleware will end up looking like a usual dispatch function:

function middleware(action) { // statements }  

What differs is that it ables to access store and the previous store.dispatch.

Back to our middleware, we’ll invoke each of the middleware, passing reference to our store, and the previous store.dispatch. Then, assigning our middleware as the new store.dispatch. This happens over and over until our list of middlewares runs out.

Seeing from our middleware, our next will be the previous store.dispatch.

You can picture this as peeling an onion, every layer is a middleware, and the innermost layer is the original store.dispatch that has the ability to invoke the reducer.