12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- <head>
- 01 to ES6
- </head>
- <body>
- <script>
- class Store {
- #reducer;
- #state;
- #cbs = []
- get state() {
- return this.#state;
- }
- getState() { return this.#state; } //функция, возвращающая переменную из замыкания
- subscribe(cb) {
- this.#cbs.push(cb); //запоминаем подписчиков в массиве
- return (cb) => {
- this.#cbs = this.#cbs.filter(c => c !== cb)
- }
- } //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
- dispatch(action) {
- /*
- if (typeof action === 'function') { //если action - не объект, а функция
- return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
- }
- */
- const newState = this.#reducer(this.#state, action) //пробуем запустить редьюсер
- if (newState !== this.#state) { //проверяем, смог ли редьюсер обработать action
- this.#state = newState //если смог, то обновляем state
- for (let cb of this.#cbs) cb() //и запускаем подписчиков
- }
- }
- constructor(reducer) {
- this.#reducer = reducer;
- this.#state = this.#reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
- }
- }
- const seller = (state, { type, item, amount, cash, price }) => {
- if (state === undefined) {
- state = {
- beer: { amount: 20, price: 10 },
- vodka: { amount: 10, price: 30 },
- cigars: { amount: 100, price: 20 },
- cashbox: 0,
- }
- }
- if (type === 'BUY' &&
- item in state &&
- typeof amount == "number" &&
- typeof cash == "number" &&
- state[item].amount >= amount &&
- amount > 0 &&
- cash > 0 &&
- state[item].price <= cash / amount) { //если тип action - КУПИТЬ, то:
- return {
- ...state, //берем все что было из ассортимента
- [item]: { amount: state[item].amount - amount, price: state[item].price }, //и уменьшаем то, что покупается на количество
- cashbox: state.cashbox + amount * state[item].price,
- }
- }
- return state;
- }
- let store = new Store(seller);
- const unsubscribe = store.subscribe(() => console.log(store.getState()))
- store.dispatch({ type: 'BUY', item: 'cigars', amount: 3, cash: 58 });
- store.dispatch({ type: 'BUY', item: 'vodka', amount: 3, cash: 92 });
- unsubscribe();
- console.log(store.state);
- </script>
- </body>
|