# Middleware (усилители)

## Middleware (Усилители).

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

Усилители, это *middleware*. Суть *middleware* функций, взять входные данные, добавить что-то и **передать дальше**.

Например: есть конвейер, по которому движется пальто. На конвейере работают Зина и Людмила. Зина пришивает пуговку, Людмила прикладывает бирку. Внезапно, появляется middleware Лена, встает между Зиной и Людмилой и красит пуговку в хипстерский модный цвет. Так как Лена после покраски не уносит пальто с собой, а **передает дальше**, то Людмила как ни в чем не бывало приделывает бирку и пальто готово. Только теперь оно хипстерское. Усиленное.

Для лучшего понимания, предлагаю написать бесполезный усилитель, выдающий `console.log('ping')`, на каждое действие. При этом, мы будем использовать предложенный redux метод добавления усилитей с помощью [applyMiddleware](https://redux.js.org/api/applymiddleware).

Обновим файл конфигурации store:

*store/configureStore.js*

```javascript
import { createStore, applyMiddleware } from 'redux'
import { rootReducer } from '../reducers'
import { ping } from './enhancers/ping' // <-- подключаем наш enhancer

export const store = createStore(rootReducer, applyMiddleware(ping)) // <-- добавляем его в цепочку middleware'ов
```

Напишем усилитель:

*store/enhancers/ping.js*

```javascript
/*eslint-disable */
export const ping = store => next => action => {
  console.log('ping')
  return next(action)
}
/*eslint-enable */
```

Боюсь, здесь не обойтись без ES5 версии:

```javascript
var ping = function ping(store) {
  return function (next) {
    return function (action) {
      console.log('ping');
      return next(action);
    };
  };
};
```

Поехали:

* *eslint-disable* - просто выключает проверку этого блока "линтером".
* ping - это функция, которая возвращает функцию. Middleware - это всегда функция, которые обычно возвращают функцию, если только целью middleware не является прервать цепочку вызовов.
* в функциях, у нас становятся доступными аргументы, которые мы можем использовать во благо приложения:
  * `store` - *redux-store* нашего приложения;
  * `next` - функция-обертка, которая позволяет продолжить выполнение цепочки;
  * `action` - действие, которое было вызвано (как вы помните, вызванные действия - это *store.dispatch*)

![ping-logger](/files/-LvLnQdms27lQ16tGkgD)

Сейчас, при клике на кнопки, у нас в консоли появляется строка ping. Давайте изменим ее, написав простейший логгер:

*store/enhancers/ping.js*

```javascript
/*eslint-disable */
export const ping = store => next => action => {
  console.log(
    `Тип события: ${action.type}, дополнительные данные события: ${
      action.payload
    }`
  )
  return next(action)
}
/*eslint-enable */
```

Я использовал новый строковый синтаксис. В прошлом, наш *console.log* выглядел бы так:

```
console.log('Тип события: ' + action.type + ', дополнительные данные события: ' + action.payload)
```

Покликайте на кнопки, результат должен быть следующим:

![ping-logger-with-type](/files/-LvLnQdpxfXGHNsW5y-i)

## Redux-logger

Отбросим наш велосипед и поставим популярный [логгер](https://github.com/evgenyrodionov/redux-logger).

```
npm i --save-dev redux-logger
```

Удалите папку enchancers, и измените configureStore.

*src/store/configureStore.js*

```javascript
import { createStore, applyMiddleware } from 'redux'
import { rootReducer } from '../reducers'
import logger from 'redux-logger'

export const store = createStore(rootReducer, applyMiddleware(logger))
```

Можете проверить - логгер достаточно информативный и удобен в использовании.

![redux-logger](/files/-LvLnQdrAXbSruE5nXwe)

Таким образом, усилители - отличный способ добавить в наш процесс обработки действий некую прослойку с необходимой функциональностью.

Одним из популярнейших усилителей, является [redux-thunk](https://github.com/reduxjs/redux-thunk), который мы как раз и будем использовать для создания асинхронных действий.

[Исходный код](https://github.com/maxfarseer/redux-course-ru-v2/tree/chp10-apply-middleware) на текущий момент.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://max-frontend.gitbook.io/redux-course-ru-v2/sozdanie/middleware-usiliteli.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
