kredux.js createStore实现 和 applyMiddleware 实现
export function createStore(reducer,enhancer) {
//如果存在enhancer
if(enhancer) {
return enhancer(createStore)(reducer)
}
let currentState = undefined;
const currentListeners = []; //回调函数数组
function getState() {
return currentState;
};
//更新状态
function dispatch(action) {
//修改
currentState = reducer(currentState,action)
//变更通知
currentListeners.forEach(v=>v())
return action;
}
function subscribe(cb) {
currentListeners.push(cb);
};
//初始化状态
dispatch({type: '@IMOCKKDEDDSDE'})
return {
getState,dispatch,subscribe
}
};
export function applyMiddleware(...middlewares) {
return createStore => (...args) => {
// 先完成之前的 createStore 工作
// debugger
const store = createStore(...args);
// 原先的 dispatch
let dispatch = store.dispatch;
// 传递给中间件函数的参数
const midApi = {
getState: store.getState,
dispatch: (...args) => dispatch(...args),
}
//将来中间件函数签名如下 : function({}) {}
// debugger
const chain = middlewares.map(mw => mw(midApi));
// 强化dispatch, 让他可以循序执行中间件函数
dispatch = compose(...chain)(store.dispatch);
//返回全新store, 仅更新强化过的dispatch
return {
...store,
dispatch
}
}
}
export function compose(...funcs) {
// debugger
if(funcs.length === 0) {
return arg=>arg;
}
if(funcs.length === 1) {
return funcs[0];
}
// 聚合函数数组为一个函数 [fn1,fn2] = fn2(fn1())
return funcs.reduce((left,right)=>(...args)=>right(left(...args)))
}
测试代码
import React, { Component } from 'react'
import {CreateStore, applyMiddleware} from './kredux';
const counterReducer = function(state=1,action) {
switch (action.type) {
case 'add':
return state +1;
case 'minus':
return state - 1;
default:
return state
}
}
//自定义logger中间件
function logger() {
return dispatch=>action=> {
console.log(action.type+'我执行啦')
return dispatch(action)
}
}
// 换种写法
const thunk = ({dispatch,getState})=>dispatch=>action=>{
if(typeof action === 'function') {
action(dispatch,getState)
}
return dispatch(action)
}
const store = CreateStore(counterReducer,applyMiddleware(logger,thunk))
export default class MyTestRedux extends Component {
componentDidMount() {
store.subscribe(()=>this.forceUpdate())
}
render () {
return (
<div>
<h3>测试</h3>
<h5>{store.getState()}</h5>
<button onClick = {()=>store.dispatch({type:'add'})}>加一下</button>
<button onClick = {()=>store.dispatch({type:'minus'})}>减一下</button>
<button onClick = {()=>store.dispatch(function(){
setTimeout(()=>{
store.dispatch({
type:'add'
})
},1000)
})}>异步加一下</button>
</div>
)
}
}
koa2 洋葱模型
async function fn1(next) {
console.log('fn1')
await next();
console.log('end fn1')
}
async function fn2(next) {
console.log('fn2')
await next();
console.log('end fn2')
}
async function fn3(next) {
console.log('fn3')
await next();
console.log('end fn3')
}
function compose2(middlewares){
return function() {
//执行第一个
return dispatch(0)
function dispatch(i) {
let fn = middlewares[i]
if(!fn){
return Promise.resolve()
}
return Promise.resolve(
fn(function next(){
//执行下一个
return dispatch(i+1)
})
)
}
}
}
const middlewares = [fn1,fn2,fn3];
const finalFn = compose2(middlewares)
finalFn()