hw_22_01Stor_ES6.html 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. <head>
  2. 01 to ES6
  3. </head>
  4. <body>
  5. <script>
  6. class Store {
  7. #reducer;
  8. #state;
  9. #cbs = []
  10. get state() {
  11. return this.#state;
  12. }
  13. getState() { return this.#state; } //функция, возвращающая переменную из замыкания
  14. subscribe(cb) {
  15. this.#cbs.push(cb); //запоминаем подписчиков в массиве
  16. return (cb) => {
  17. this.#cbs = this.#cbs.filter(c => c !== cb)
  18. }
  19. } //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
  20. dispatch(action) {
  21. /*
  22. if (typeof action === 'function') { //если action - не объект, а функция
  23. return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
  24. }
  25. */
  26. const newState = this.#reducer(this.#state, action) //пробуем запустить редьюсер
  27. if (newState !== this.#state) { //проверяем, смог ли редьюсер обработать action
  28. this.#state = newState //если смог, то обновляем state
  29. for (let cb of this.#cbs) cb() //и запускаем подписчиков
  30. }
  31. }
  32. constructor(reducer) {
  33. this.#reducer = reducer;
  34. this.#state = this.#reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  35. }
  36. }
  37. const seller = (state, { type, item, amount, cash, price }) => {
  38. if (state === undefined) {
  39. state = {
  40. beer: { amount: 20, price: 10 },
  41. vodka: { amount: 10, price: 30 },
  42. cigars: { amount: 100, price: 20 },
  43. cashbox: 0,
  44. }
  45. }
  46. if (type === 'BUY' &&
  47. item in state &&
  48. typeof amount == "number" &&
  49. typeof cash == "number" &&
  50. state[item].amount >= amount &&
  51. amount > 0 &&
  52. cash > 0 &&
  53. state[item].price <= cash / amount) { //если тип action - КУПИТЬ, то:
  54. return {
  55. ...state, //берем все что было из ассортимента
  56. [item]: { amount: state[item].amount - amount, price: state[item].price }, //и уменьшаем то, что покупается на количество
  57. cashbox: state.cashbox + amount * state[item].price,
  58. }
  59. }
  60. return state;
  61. }
  62. let store = new Store(seller);
  63. const unsubscribe = store.subscribe(() => console.log(store.getState()))
  64. store.dispatch({ type: 'BUY', item: 'cigars', amount: 3, cash: 58 });
  65. store.dispatch({ type: 'BUY', item: 'vodka', amount: 3, cash: 92 });
  66. unsubscribe();
  67. console.log(store.state);
  68. </script>
  69. </body>