123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- <header>reducers</header>
- <body>
- <div id="testDiv">
- Test
- </div>
- <script>
- function promiseReducer(state = {}, action) { // диспетчер обработки
- if (action) {
- if (action.type === 'PROMISE') {
- let newState = { ...state };
- newState[action.name] = { status: action.status, payload: action.payload, error: action.error };
- return newState;
- }
- }
- return state;
- }
- function createStore(reducer) {
- let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
- let cbs = [] //массив подписчиков
- const getState = () => state //функция, возвращающая переменную из замыкания
- const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
- () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
- function dispatch(action) {
- if (typeof action === 'function') { //если action - не объект, а функция
- return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
- }
- const newState = reducer(state, action) //пробуем запустить редьюсер
- if (newState !== state) { //проверяем, смог ли редьюсер обработать action
- state = newState //если смог, то обновляем state
- for (let cb of cbs) cb() //и запускаем подписчиков
- }
- }
- return {
- getState, //добавление функции getState в результирующий объект
- dispatch,
- subscribe //добавление subscribe в объект
- }
- }
- function actionPromise(name, promise) {
- return async function Exec(dispatch) {
- dispatch(actionPending(name)) //сигнализируем redux, что промис начался
- try {
- const payload = await promise //ожидаем промиса;
- dispatch(actionFulfilled(name, payload)); //сигнализируем redux, что промис успешно выполнен
- return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
- }
- catch (error) {
- dispatch(actionRejected(name, error)) //в случае ошибки - сигнализируем redux, что промис несложился
- }
- };
- }
- const actionPending = (name) => ({ type: 'PROMISE', name: name, status: 'PENDING' });
- const actionFulfilled = (name, payload) => ({ type: 'PROMISE', name: name, payload: payload, status: 'FULFILLED' });
- const actionRejected = (name, error) => ({ type: 'PROMISE', name: name, error: error, status: 'REJECTED' });
- const store = createStore(promiseReducer);
- store.subscribe(() => {
- console.log(store.getState())
- });
- store.dispatch(actionPromise('luke', fetch("https://swapi.dev/api/people/1").then(res => res.json())))
- //let execFunc = actionPromise({ name: "auth", promise: signIn("test457", "123123", "http://shop-roles.node.ed.asmer.org.ua/graphql") });
- // store.dispatch(execFunc);
- /*
- const actionPending = () => ({ type: 'PROMISE', status: 'PENDING' })
- const actionFulfilled = payload => ({ type: 'PROMISE', status: 'FULFILLED', payload })
- const actionRejected = error => ({ type: 'PROMISE', status: 'REJECTED', error })
-
-
- store.subscribe(() => console.log(store.getState()))
-
- store.dispatch({ type: 'COUNTER_INC' })
- store.dispatch({ type: 'BOOLEAN_SET' })
- store.dispatch({ type: 'COUNTER_INC' })
- store.dispatch({ type: 'BOOLEAN_TOGGLE' })
- store.dispatch({ type: 'COUNTER_DEC' })
- store.dispatch({ type: 'ДИЧЬ' }) //не вызывает подписчика
- */
- </script>
- </body>
|