Zorgen om de wereld

Soms heb je van die dagen, dat je je zorgen maakt om de wereld. Dat je je zorgen maakt hoe dit afloopt. Het is net alsof je weer op het schoolplein staat, onzeker, en dat je niet gepest wordt, maar…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Making of A Middleware

Middleware is a pattern used to enhance communication between two or more connected systems. Web servers, application servers and content management system heavily uses this pattern.

If we have to consider it, Redux middleware exposes a platform to extend the contract between two systems — action dispatcher and reducer.

Here the contract is a plain action object which we pass to the store.dispatch method.

What could be some of the possible enhancements?

To achieve these, we need to modify the store.dispatcher for every enhancement.

A middleware is an enhancer to the original functionality. So, after the enhancement, it should preserve the signature of the original function.

So, if we have a logger middleware which logs state and action, pre and post dispatch, it should return a function which retains the same signature as store.dispatcher — accept a plain object describing the action.

The function dispatchAndLog at 📍1 will be our new store.dispatch.

This style of replacing the definition of a function with some enhancement wrapped around the original function is called monkey patching. Although this is an ugy way to extend functionality, it will do for our understanding the problem at hand.

This would work fine if we only had to enhance our store once.

But in practice, we will have multiple enhancers. And the order in which enhancers are applied one over the other is important. So, we will end up with an array of middlewares.

But before we proceed to further understand how best to enhance our store.dispatcher with multiple middlewares, we need to be aware of two primary ideas.

Function assignments assigns value not reference

When we assign a function to a variable, say cache, it stores a copy of the function. So, if even if we overwrite the initially assigned function, the variable cache would refer to the older definition.

Closures

Whenever a function returns a function, the inner function has access to the scope of the outer function which means the scope of the outer function lives as long as the inner function is not garbage collected.

Okay, back to middlewares.

A middleware is made by packing enhancers on top of the original function. And when an action is dispatched with the enhanced store.dispatch, the action flows through each enhancer in the pack before reaching the original store.dispatch.

This packing happens just after a redux store is initialized and before any action is dispatched. Redux exposes its own API to do ths packing. It is called applyMiddleware.

This applyMiddleware omits certain nuances for the sake of understanding. It uses monkey patching. The one provided by Redux builds on top of this, but it behaves in a similar way.

The packing is happening in 📍3.

middleware(store) will return a new function akin to store.dispatch but now enhanced by the middleware.

And for every middleware in the array of middlewares we keep overwriting store.dispatch with a new enhanced store.dispatch.

After the loop ends we have an enhanced store.dispatch packed with all the middlewares.

So, when an action is dispatched, it will flow through each middleware in the pack.

Now the question which confused me was, how this one line is maintaining the link between each middleware in the pack.

The answer lies in the definition of each middlware.

Every middleware has to be defined in a very particular way.

Lets take a look at logger middleware again.

A key fact here is that the statement at📍5 gets executed while we are packing the middlewares in 📍4.

Statement at 📍6 gets executed every time an action is dispatched and it flows through the pack of middlewares to reach this particular middleware.

The variable next at statement 📍5 takes a snapshot of store.dispatch at that point in time. This can be explained by the idea that function assignment is a copy of value not reference. So, even if store.dispatch gets overwritten in the next cycle of the loop, next will retain the snapshot.

Take a note that after logging the action, it is passed to next which got defined in 📍5.

next sits outside the scope of the middleware function and hence the middleware function closes over the value of next in 📍5 which is a snapshot of the next middleware in the pack.

This reference to next gets hidden under the rug when we look at the definition of applyMiddleware which I think is a source of confusion.

So, every middleware closes over the next middleware. And this is how one middleware passes the action to the next.

And the chain prevails.

Add a comment

Related posts:

Is Silver Set to Soar?

An article published on the business journal’s website last week predicted the white metal will emerge as a winner for the second straight year. Peter Schiff talked about the silver-gold ratio over…