-
Notifications
You must be signed in to change notification settings - Fork 632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
介绍 Redux 原理,并手写一个 Redux #140
Comments
function compose(...funcs) {
if (funcs.length === 0) {
return args => args;
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce((next, cur) => (...args) => next(cur(...args)));
}
function createThunkMiddleWare(args) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, args);
}
return next(action);
}
}
function createPromiseMiddleWare({ dispatch }) {
return next => action => {
if (action instanceof Promise) {
return action.then((v) => dispatch(v))
}
return next(action)
}
}
const thunk = createThunkMiddleWare();
function applyMiddleWares(...middlewares) {
return createStore => (...args) => {
const store = createStore(...args);
let dispatch = () => {
throw Error('not allow dispatch in construct middleware period.');
}
// 增强 dispatch 方法
const middleAPI = {
// 这块非常关键
// 1.避免在构建过程中被调用
// 2.传递action对象,最终被 next(action) 执行
dispatch: (...args) => dispatch(...args),
getState: store.getState,
};
const chain = middlewares.map(ware => ware(middleAPI));
// 改写dispatch 接收action,
dispatch = compose(...chain)(store.dispatch);
return {
...store,
dispatch,
};
}
}
function createStore(reducer, inititalState, enhancer) {
let currentState = inititalState;
let currentReducer = reducer;
let currentEnhancer = enhancer;
let listenerList = [];
let isDispatching = false;
if (typeof inititalState === 'function' && typeof enhancer === 'undefined') {
currentState = {};
currentEnhancer = inititalState;
}
if (currentEnhancer) {
return enhancer(createStore)(reducer, inititalState);
}
function getState() {
return currentState;
}
function dispatch(action) {
if (!action.type) {
throw Error('is not standrad action.');
}
if (isDispatching) {
throw Error('not allow dispatch in dispatch function.');
}
try {
isDispatching = true;
currentState = currentReducer(currentState, action);
listenerList.forEach(lis => lis(currentState));
} finally {
isDispatching = false;
}
}
function subscribe(listener) {
if (typeof listener !== 'function') {
throw Error('listener not a funciton.')
}
const idx = listenerList.length;
listenerList = [...listenerList, listener];
return () => {
listenerList.splice(idx, 1);
}
}
return {
getState,
dispatch,
subscribe,
}
}
const reducer = (state, action) => {
if (action.type === 'add') {
state.count += 1;
}
if (action.type === 'sub') {
state.count -= 1;
}
return state;
}
// const enhancer = applyMiddleWares(thunk);
const enhancer = applyMiddleWares(createPromiseMiddleWare);
const myStore = createStore(reducer, { count: 0 }, enhancer);
// myStore.dispatch((dispatch) => {
// console.log('something');
// dispatch({ type: 'add' });
// });
myStore.dispatch(new Promise(r => {
setTimeout(() => {
r({ type: 'add' })
}, 1000);
}))
myStore.subscribe((state) => {
console.log('subscribe', state)
})
console.log(myStore.getState()); // {count: 1} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
No description provided.
The text was updated successfully, but these errors were encountered: