Рубрики
Без рубрики

Руководство для начинающих к промежуточным программного обеспечении Redux

Эта статья представит новичку для реагирования и Redux для промежуточного программного обеспечения Redux.

Автор оригинала: Valeri Karpov.

Redux Стал состоятельный контейнер выбора для реагированных приложений. Основная идея, которая делает Redux настолько популярным, состоит в том, что ваша заявка логика живет в «редукторах», которые являются функциями JavaScript, которые принимают в состояние и действие, и возвращает новое состояние. Редукторы являются чистыми функциями: они не полагаются на или изменит любое глобальное состояние, поэтому их легко проверить, разум, и рефакторист. Например, вот магазин Redux, который отслеживает счетчик:

const redux = require('redux');

const counter = (state = 0, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
  }
  return state;
};

const store = redux.createStore(counter);

После того, как у вас есть магазин redux, вы можете подписаться на государственные изменения в хранилище и отправках:

store.subscribe(() => { console.log(store.getState()); });

store.dispatch({ type: 'INCREMENT' }); // Prints "1"

Редукторы – это элегантный инструмент для управления состоянием, но они не полная история, когда речь идет о создании приложений с Redux. Если вы посмотрите внимательно, вы заметите 2 неявные ограничения на то, что могут сделать редукторы Redux:

  • Редукторы Должен быть синхронно. Они Возвращение Новое состояние.
  • Поскольку редукторы не должны изменять глобальное состояние, редукторы не должны использовать такие функции, как setinterval ()

Допустим, вы хотите использовать redux в качестве контейнера для состояния для приложения секундомера: приложение должно иметь возможность отображать прошедшее время на экране, а затем сохранить прошедшее время на сервер, используя HTTP-запрос. Редукторы отлично подходят для преобразования состояния из-за синхронных действий, таких как кнопки, но что происходит, когда вам нужно бросить асинхронное поведение в смесь? Вот где приходит идея промежуточного программного обеспечения.

Представляя промежуточное программное обеспечение

Ваше приложение STOPWACT требует возможности отображения прошедшего времени. Правильный способ сделать это для вашего редуктора, чтобы прослушать 3 действия:

  • Start_timer , уволен, когда запускается таймер
  • Галочка , уволен, когда вы должны изменить текущее количество времени, прошедшего
  • Stop_timer , уволен, когда вы не собираетесь получать больше Галочка Действия.

Вот как выглядит редуктор:

const stopwatch = (state = {}, action) => {
  switch (action.type) {
    case 'START_TIMER':
      return Object.assign({}, state, { startTime: action.currentTime, elapsed: 0 });
    case 'TICK':
      return Object.assign({}, state, { elapsed: action.currentTime - state.startTime });
    case 'STOP_TIMER':
      return state;
  }
  return state;
};

const store = redux.createStore(stopwatch);

Вышеуказанная функция является просто простым старым редуктором: он не полагается на или изменяет глобальное состояние, и он полностью синхронно. Когда пользователь нажимает кнопку, чтобы начать таймер, вы можете отправить Start_timer Событие, и когда они нажимают кнопку, чтобы остановить таймер, вы отправляете Stop_timer Отказ

Тем не менее, есть проблема: вам нужно периодически отправлять Галочка События для обновления прошедшего времени. Вы можете позвонить SetInterval () В Start_timer Заявление об случаях, но затем ваш редуктор изменяет глобальное состояние, и вы нарушаете лучшие практики Redux. Правильное место для периодической отправки Галочка События в промежуточное программное обеспечение :

const timerMiddleware = store => next => action => {
  if (action.type === 'START_TIMER') {
    action.interval = setInterval(() => store.dispatch({ type: 'TICK', currentTime: Date.now() }), 1000);
  } else if (action.type === 'STOP_TIMER') {
    clearInterval(action.interval);
  }
  next(action);
};

const stopwatch = (state = {}, action) => {
  switch (action.type) {
    case 'START_TIMER':
      return Object.assign({}, state, {
        startTime: action.currentTime,
        elapsed: 0,
        interval: action.interval
      });
    case 'TICK':
      return Object.assign({}, state, { elapsed: action.currentTime - state.startTime });
    case 'STOP_TIMER':
      return Object.assign({}, state, { interval: null });
  }
  return state;
};

const middleware = redux.applyMiddleware(timerMiddleware);
const store = redux.createStore(stopwatch, middleware);

Синтаксис промежуточного программного обеспечения Redux является глотком: функция промежуточного программного обеспечения – это функция, которая возвращает функцию, которая возвращает функцию. Первая функция берет магазин Как параметр, второй берет Следующий Функция как параметр, а третий берет Действие отправлен в качестве параметра. магазин и Действие Параметры – текущий магазин Redux и Diage Dispatched соответственно. Настоящая магия – это Далее () функция. Далее () Функция – это то, что вы звоните, чтобы сказать «Это промежуточное программное обеспечение выполняется выполнение, передайте это действие на следующее промежуточное программное обеспечение». Другими словами, промежуточное программное обеспечение может быть асинхронной.

Timermiddleware Функция выше несет ответственность за управление SetInterval () Функция, включая очистку интервала, когда Stop_timer Действие отправляется. Redux звонит Timermiddleware Функция, когда появляется новое действие, до Редуктор. Это означает, что промежуточное программное обеспечение может преобразовать действия по мере необходимости, включая распределять новые действия. Когда вы запустите вышеуказанный код в Node.js, вы должны увидеть примерно ниже вывода.

$ node
> const store = require('./test.js');
undefined
> store.subscribe(() => console.log(store.getState().elapsed));
[Function: unsubscribe]
> store.dispatch({ type: 'START_TIMER', currentTime: Date.now() });
0
undefined
> 1002
2005
3013
4015
5017
6019
7021
store.dispatch({ type: 'STOP_TIMER' })
7021
undefined
>

Отлично, у вас сейчас есть рабочий таймер в Redux! Галочка События опускаются примерно раз в секунду, поэтому вы получите изменение периодического состояния с прошедшим временем.

Разрешение обещаний с промежуточным программным обеспечением

Теперь у вас есть рабочий секундомер, но ваше приложение все еще должно быть в состоянии сэкономить время на сервере. Как вы собираетесь обрабатывать HTTP-запросы в Redux? Ключ Далее () Функция и Обещания :

const timerMiddleware = store => next => action => {
  if (action.type === 'START_TIMER') {
    action.interval = setInterval(() => store.dispatch({ type: 'TICK', currentTime: Date.now() }), 1000);
  } else if (action.type === 'STOP_TIMER') {
    clearInterval(action.interval);
  }
  // next() passes an action to the next middleware, or to the reducer if
  // there's no next middleware
  next(action);
};

Помните, что промежуточное программное обеспечение может быть асинхронной. Далее () Функция – это механизм управления потоком промежуточного программного обеспечения: это то, как вы отложите контроль на следующую промежуточное программное обеспечение в цепочке. Вы можете позвонить Далее () асинхронно или даже совсем нет. Вы можете создать промежуточное программное обеспечение, которое разрешается для вас обещаний. Если вы отправляете действие с помощью полезная нагрузка Собственность, которое обещание, промежуточное программное обеспечение будет ждать этого обещания разрешить или отклонить перед вызовом Далее () Отказ

const promiseMiddleware = store => next => action => {
  // check if the `payload` property is a promise, and, if so, wait for it to resolve
  if (action.payload && typeof action.payload.then === 'function') {
    action.payload.then(
      res => { action.payload = res; next(action); },
      err => { action.error = err; next(action); });
  } else {
    // no-op if the `payload` property is not a promise
    next(action);
  }
};

Вы можете добавить это промежуточное программное обеспечение на ваш магазин Redux, используя CreateMiddleware () функция.

// Order of execution is timerMiddleware first, promiseMiddleware second
const middleware = redux.applyMiddleware(timerMiddleware, promiseMiddleware);
const store = redux.createStore(stopwatch, middleware);

Как эта справка с HTTP-запросами в Redux? Клиенты HTTP, такие как SuperaGent Вернуть обещание – совместимые интерфейсы, поэтому, если вы устанавливаете полезную нагрузку на действие в запрос SuperAgent, priesemiddleware будет дождаться просьбы завершить до того, как пройдет действие вместе.

const superagent = require('superagent');

store.dispatch({ type: 'SAVE_TIME', payload: superagent.post('/save', store.getState()) });

Вышеуказанное Отправка () Вызов сохранит прошедшее время на сервере. Все ваши редукторы должны сделать, это справиться с результатом.

const stopwatch = (state = {}, action) => {
  switch (action.type) {
    case 'START_TIMER':
      return Object.assign({}, state, {
        startTime: action.currentTime,
        elapsed: 0,
        interval: action.interval
      });
    case 'TICK':
      return Object.assign({}, state, { elapsed: action.currentTime - state.startTime });
    case 'STOP_TIMER':
      return Object.assign({}, state, { interval: null });
    case 'SAVE_TIME':
      // If there was an error, set the error property on the state
      if (action.error) {
        return Object.assign({}, state, { error: action.error });
      }
      // Otherwise, clear all the timer state
      return Object.assign({}, state, { startTime: null, elapsed: null, error: null });
  }
  return state;
};

В парадигме Redux ваш редуктор должен отвечать за любые модификации государству. Ваше промежуточное программное обеспечение должно не изменить состояние. Тем не менее, ваше промежуточное программное обеспечение должно отвечать за любые взаимодействия, которые влияют на глобальное состояние (например Setinterval () ) или любые асинхронные операции (например, HTTP-запросы).

Другие приложения промежуточного программного обеспечения

При разрешении обещаний является наиболее распространенным применением для промежуточного программного обеспечения, существует множество других случаев использования для промежуточного программного обеспечения.

  • Логирование:
const loggerMiddleware = store => next => action => {
  console.log(action.type);
  next(action);
}
  • Показывая сообщение тоста, когда есть ошибка, используя Ванильятасты :
const toastMiddleware = store => next => action => {
  if (action.error) {
    vanillatoasts.create({ text: action.error.toString(), timeout: 5000 });
  }
  next(action);
};
const confirmationMiddleware = store => next => action => {
  if (action.shouldConfirm) {
    if (confirm('Are you sure?')) {
      next(action);
    }
  } else {
    next(action);
  }
};

Следующие шаги

Помесление необходима для создания любого нетривиального приложения Redux. Любое асинхронное поведение или глобальные модификации состояния должны проходить через промежуточное программное обеспечение, поэтому ваши редукторы могут быть чистыми функциями. Если вы заинтересованы в том, чтобы узнать больше о том, как использовать промежуточное программное обеспечение для создания приложений Red-World Redux, проверьте Это пример приложения , что является Средний Клон написан в реакции с redux в качестве состояния контейнера. Это приложение является основой для предстоящего видео курса на Thinkster О redux, поэтому зарегистрируйтесь на Github Для обновлений!