123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- 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, которая удаляет подписчика из списка
- const 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 promiseReducer(state = {}, {promiseName, type, status, payload, error}) {
- if (type === 'PROMISE') {
- return {...state, [promiseName]: {status, payload, error}}
- }
- return state
- }
- const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms));
- const actionPending = promiseName => ({promiseName, type: 'PROMISE', status: 'PENDING'})
- const actionFulfilled = (promiseName, payload) => ({promiseName, type: 'PROMISE', status: 'FULFILLED', payload})
- const actionRejected = (promiseName, error) => ({promiseName, type: 'PROMISE', status: 'REJECTED', error})
- const actionPromise = (promiseName, promise) =>
- async dispatch => {
- dispatch(actionPending(promiseName)) //сигнализируем redux, что промис начался
- try {
- const payload = await promise //ожидаем промиса
- dispatch(actionFulfilled(promiseName, payload)) //сигнализируем redux, что промис успешно выполнен
- return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
- } catch (error) {
- dispatch(actionRejected(promiseName, error)) //в случае ошибки - сигнализируем redux, что промис несложился
- }
- }
- const store = createStore(promiseReducer)
- store.subscribe(() => console.log(store.getState())) //должен запускаться 6 раз
- store.dispatch(actionPromise('delay', delay(1000)))
- store.dispatch(actionPromise('luke', fetch("https://swapi.dev/api/people/1").then(res => res.json())))
- store.dispatch(actionPromise('tatooine', fetch("https://swapi.dev/api/planets/1").then(res => res.json())))
- /////////////////////////////////////////////////////////////////////
- function authReducer (state={}, {token, type}){
- if (type === 'AUTH_LOGIN') {
- try {
- let str = token.split('.')[1];
- let result = JSON.parse(atob(str))
- return {...state, 'token': token, 'playload':result}
- } catch (e) {
- return {}
- }
- }
- else if (type === 'AUTH_LOGOUT') {
- return {}
- }
- return state
- }
- const actionAuthLogin = token => ({type: 'AUTH_LOGIN', token})
- const actionAuthLogout = () => ({type: 'AUTH_LOGOUT'})
- const token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2Mzc3ZTEzM2I3NGUxZjVmMmVjMWMxMjUiLCJsb2dpbiI6InRlc3Q1IiwiYWNsIjpbIjYzNzdlMTMzYjc0ZTFmNWYyZWMxYzEyNSIsInVzZXIiXX0sImlhdCI6MTY2ODgxMjQ1OH0.t1eQlRwkcP7v9JxUPMo3dcGKprH-uy8ujukNI7xE3A0"
- const storeAuth = createStore(authReducer)
- storeAuth.subscribe(() => console.log(storeAuth.getState()))
- storeAuth.dispatch(actionAuthLogin(token))
- // ///////////////////////////////////////////////////////////////////////
- function cartReducer (state = {}, {type, good, count}) {
- let goodKey, oldCount, goodValue;
- if (good) {
- goodKey = good['_id'];
- oldCount = state[goodKey]?.count || 0;
- goodValue = {good, count: oldCount}
- }
- if (type === 'CARD_ADD') {
- goodValue.count += count;
- return {...state, [goodKey]: goodValue}
- }
- else if (type === 'CART_DEL') {
- delete state[goodKey];
- }
- }
- const actionCartAdd = (good, count=1) => ({type: 'CART_ADD', count, good})
- const actionCartSub = (good, count=1) => ({type: 'CART_SUB', count, good})
- const actionCartDel = (good) => ({type: 'CART_DEL', good})
- const actionCartSet = (good, count=1) => ({type: 'CART_SET', count, good})
- const actionCartClear = () => ({type: 'CART_CLEAR'})
- /////////////////////////////////////////////////////////////////
|