
Асинхронные операции - сложная задача при программировании браузера.
Трудно представить себе отправку запроса и ожидание ответа без блокировки. Браузеры могут поместить запрос после обратного вызова и продолжить выполнение кода.
Библиотеки React-Redux делают большую часть работы за вас без ущерба для простоты. Думайте о React как о библиотеке, которая отображает компоненты пользовательского интерфейса в виде простого HTML. Redux - это библиотека управления состоянием с асинхронными возможностями.
Раньше вы могли делегировать асинхронное поведение через связанные обратные вызовы. У этого были ограничения, потому что большая цепочка обратных вызовов грозила адом обратных вызовов. Чтобы код был как можно более чистым, требовалось сильное чувство дисциплины. Ад обратных вызовов может превратить любой проект в кашу, если вам не хватает принципов SOLID.
Но какие улучшения доступны в асинхронном программировании с помощью React-Redux? Для этого мы проведем демонстрацию планет Солнечной системы. Цель состоит в том, чтобы загрузить их на страницу асинхронно с изображениями. Мы сосредоточимся на управлении состоянием Redux и на том, как он обрабатывает асинхронное поведение. Предположим, вы уже знакомы с npm и ES6. Чтобы примеры кода не теряли актуальности, мы показываем только релевантный код. Если вас интересует больше сантехники, не стесняйтесь проверить всю демонстрацию на GitHub.
Зависимости для этой демонстрации будут следующими: если вы следите за новостями, введите:
npm install --save next react react-dom prop-types axios redux react-redux redux-thunk redux-logger
Убедитесь, что доступен package.json для сохранения всех зависимостей. Не стесняйтесь исследовать, что будет делать каждая зависимость. Следует иметь в виду, что axios выполняет асинхронные запросы и redux-thunk управляет асинхронным состоянием.
Для начала, константы захвата, которые мы будем использовать на протяжении всей демонстрации. Эти константы будут управлять состоянием асинхронных операций:
export const REQUEST_PLANETS = 'request planets'; export const RECEIVE_PLANETS = 'receive planets';
Запрос запускается componentDidMount методом компонента, который затем запускает fetchPlanets. Чтобы помочь вам визуализировать результат, вот рабочая демонстрация:

Почему бы не использовать Ajax?
Вы можете думать о Redux-Thunk как о еще одном способе работы с Ajax в браузере. Преобразователь описывает функцию, которая заменяет вычисление, которое вы затем вычисляете позже. Выполнение происходит не сразу, а делегируется.
Например:
const foo = (i) => i + 1;
В JavaScript вы можете думать о преобразователе как о функции обратного вызова. Функция обратного вызова делегирует вычисления, чтобы их можно было выполнить позже. В Redux-Thunk вы по-прежнему используете ту же концепцию обратного вызова, но абстрактным образом. Система управления операторами Redux обрабатывает все детали реализации. Это исключает риск длинных цепочек обратных вызовов и ада обратных вызовов.
Пора подключить Redux-Thunk в Redux-Store:
const logger = createLogger(); const planetStore = createStore( reducers, applyMiddleware(logger, thunk) );
Итак, вы готовы к асинхронному программированию. Thunk теперь настраивает диспетчеров действий, чтобы он мог обрабатывать функцию обратного вызова thunk. Redux-Store - это место, где вы настраиваете Redux-Thunk в качестве конвейера промежуточного программного обеспечения. Обратите внимание, что мы пользуемся этой возможностью, чтобы включить регистратор, чтобы мы могли увидеть Redux-Thunk в действии. Регистратор фиксирует сообщения диспетчера и печатает их в консоли браузера.
Асинхронные действия с Axios
Затем давайте настроим действия, которые будут отправляться через магазин. В Redux действия похожи на сообщения, которые передаются по системе управления состоянием. Вы можете думать о любом взаимодействии с пользовательским интерфейсом как о действии. Это хорошо подходит, когда вы представляете запуск и получение сообщений для управления состоянием. Пользовательский интерфейс отмечает изменение состояния, запускает действие, а Redux обрабатывает изменения состояния посредством сообщений.
PlanetAction выглядит следующим образом:
let PlanetAction = {
fetchPlanets() {
return (dispatch) => {
dispatch({ type: REQUEST_PLANETS });
axios.get('/static/solar-system-planets.json')
.then((response) => dispatch({
type: RECEIVE_PLANETS,
success: true,
planets: response.data.planets
}))
.catch((error) => dispatch({
type: RECEIVE_PLANETS,
error: error.message,
planets: null
}));
};
}
};
Обратите внимание на использование axios для инкапсуляции запросов Ajax в браузере через обещание. Функция .then() обрабатывает успешный ответ. Функция .catch() обрабатывает ошибку. React-Thunk позволяет использовать преобразователь в качестве возвращаемого типа. Базовая система управления состоянием обрабатывает диспетчер. Обратите внимание на использование преобразователя с return (dispatch) => { }.
Чтобы корректно обрабатывать ошибки, мы решили фиксировать error.message в сообщении диспетчера. Это помогает нам отлаживать приложение, потому что это сообщение отображается в консоли. Функция .catch() позволяет обрабатывать ошибки с помощью функции обратного вызова диспетчера.
Вот как выглядят сообщения в консоли:

Редукторы React
Редуктор принимает сообщения и возвращает текущее состояние через чистую функцию. Чистая функция - это функция, при вводе которой вы всегда получаете один и тот же результат. Эта парадигма - функциональное программирование, и она уменьшает непредсказуемое поведение в ваших программах.
Ниже представлен редуктор, который меняет состояние во время асинхронных операций:
const INITIAL_STATE = [];
const planets = (state = INITIAL_STATE, action) => {
switch (action.type) {
case REQUEST_PLANETS:
return INITIAL_STATE;
case RECEIVE_PLANETS:
return action.planets;
default:
return state;
}
};
Мы можем использовать INITIAL_STATE повторно, потому что приложение имеет одни и те же данные при загрузке страницы и во время запроса. Обратите внимание, что результат всегда будет соответствовать заданному входу один к одному. Редукторы используют чистую функцию и возвращают состояние с учетом того, где вы находитесь в асинхронной операции. Затем диспетчер действий использует эту чистую функцию для вычисления текущего состояния. Обратите внимание, что этот редуктор является функцией обратного вызова внутри функции преобразователя.
Теперь ниже показан счастливый путь с консольными сообщениями:

Вывод
Redux-Thunk имеет асинхронный подход, который охватывает функцию преобразователя. Это включает в себя лучшее из программирования, такое как делегаты и чистые функции.
Если вы знакомы с устаревшим Ajax через обратные вызовы, то преобразователь не сильно отличается. React-Redux берет лучшее из того, что вы знаете о ванильном JavaScript, и обертывает его для облегчения использования. Эта библиотека не изобретает велосипед, а автоматизирует звуковое программирование с помощью абстракций.
И последнее, но не менее важное: если вы разрабатываете приложения JavaScript и хотите защитить их от кражи кода и реверс-инжиниринга, обязательно отметьте Jscrambler.
Первоначально опубликовано на blog.jscrambler.com.