script.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. function promiseReducer(state={}, {type, name, status, payload, error}){
  2. if (type === 'PROMISE'){
  3. return {
  4. ...state, [name]: {status, payload, error}
  5. }
  6. }
  7. return state
  8. }
  9. const actionPending = name => ({type:'PROMISE',name, status: 'PENDING'})
  10. const actionFulfilled = (name,payload) => ({type:'PROMISE',name, status: 'FULFILLED', payload})
  11. const actionRejected = (name,error) => ({type:'PROMISE',name, status: 'REJECTED', error})
  12. const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
  13. function createStore(reducer){
  14. let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  15. let cbs = [] //массив подписчиков
  16. const getState = () => state //функция, возвращающая переменную из замыкания
  17. const subscribe = cb => (cbs.push(cb), //запоминаем подписчиков в массиве
  18. () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  19. const dispatch = action => {
  20. if (typeof action === 'function'){ //если action - не объект, а функция
  21. return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
  22. }
  23. const newState = reducer(state, action) //пробуем запустить редьюсер
  24. if (newState !== state){ //проверяем, смог ли редьюсер обработать action
  25. state = newState //если смог, то обновляем state
  26. for (let cb of cbs) cb() //и запускаем подписчиков
  27. }
  28. }
  29. return {
  30. getState, //добавление функции getState в результирующий объект
  31. dispatch,
  32. subscribe //добавление subscribe в объект
  33. }
  34. }
  35. let store = createStore(promiseReducer);
  36. store.subscribe(() => console.log(store.getState()))
  37. // store.dispatch(actionPending('delay1000'))
  38. // delay(1000).then(result => store.dispatch(actionFulfilled('delay1000', result)))
  39. // store.dispatch(actionPending('delay2000'))
  40. // delay(2000).then(result => store.dispatch(actionFulfilled('delay2000', result)))
  41. const actionPromise = (name, promise) =>
  42. async dispatch => {
  43. dispatch(actionPending(name))
  44. try {
  45. let payload = await promise
  46. dispatch(actionFulfilled(name, payload))
  47. return payload
  48. }
  49. catch(error){
  50. dispatch(actionRejected(name, error))
  51. }
  52. }
  53. store.dispatch(actionPromise('delay1000', delay(1000)))
  54. store.dispatch(actionPromise('delay2000', delay(2000)))
  55. const actionLuke = () => actionPromise('luke',
  56. fetch('https://swapi.dev/api/people/1')
  57. .then(res => res.json()))
  58. store.dispatch(actionLuke())
  59. // const actionRegister = (login, password) =>
  60. // actionPromise('register', gql(`mutation ......
  61. // ......
  62. // ....`, {login, password}))
  63. // store.dispatch(actionRegister('anon100500', '123123'))
  64. // const actionCategoryById = _id =>
  65. // actionPromise('catById', gql(`aaaaaaaa $query.....`, {query: JSON.stringify([{_id}])}))
  66. // store.dispatch(actionCategoryById('АЙДИКАТЕГОРИИ НАТЫРИТЬ В GRAPHQL'))
  67. // const actionGoodById = _id =>
  68. // actionPromise('goodById', gql(`aaaaaaaa $query.....`, {query: JSON.stringify([{_id}])}))
  69. // const actionRootCategories = () =>
  70. // actionPromise('rootCats', gql(`CategoryFind так, что бы parent: null`)}))
  71. // //сделать const actionOrders для истории заказов (нужен токен в localStorage)
  72. // //шобы сработало, надо добавить в createStore в dispatch один if:
  73. // //if (typeof action === 'function'){ //если action - не объект, а функция
  74. // //return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
  75. // //}
  76. // //надо const newState