Мидълуер · Redux

Виждали сте междинен софтуер в действие в примера за асинхронни действия. Ако някога сте използвали сървърни библиотеки като Express и Koa, вероятно вече сте запознати с концепцията за междинен софтуер. В тези рамки мидълуерите са части от код, които можете да поставите между рамката, която получава заявката, и рамката, която генерира отговора. Например междинният софтуер от Express или Koa може да добавя CORS заглавки, регистриране, компресия и т.н. Най-добрата характеристика на мидълуера е, че те могат да бъдат верижни/последователни. Можете да използвате много независими междинни програми на трети страни в един проект.

Мидълуерите Redux, за разлика от мидълуерите Express или Koa, решават малко по-различни проблеми, но по концептуално подобен начин.Те предоставят точка на разширение на трета страна между изпращането на действие и момента, в който това действие достигне редуктора. Хората използват Redux мидълуер за регистриране, докладване на грешки, комуникация с асинхронни API, маршрутизиране и т.н.

Разбиране на междинния софтуер

защото Мидълуерът може да се използва за различни задачи, включително асинхронни API извиквания, така че е важно да разберете откъде идват. Ще ви покажем потока от мисли, водещи до междинния софтуер стъпка по стъпка, като използваме регистриране и докладване на грешки като пример.

Проблем: регистриране

Едно от предимствата на Redux е, че прави промените в състоянието на приложението предвидими и прозрачни. Всеки път, когато се изпрати действие, се изчислява и съхранява ново състояние. Състоянието не може да се промени само по себе си, то може да се промени само като последователност от определени действия.

Как да подходим към това с Redux?

Опит №1: Ръчно регистриране

Най-простото решение е самирегистрирайте действието и посочете всеки път, когато извикате store.dispatch(action). Това всъщност не е много добро решение, това е само първата стъпка към разбирането на проблема.

Забележка

Ако използвате react-redux или подобно обвързване, вероятно искате да имате директен достъп до екземпляра на състоянието във вашите компоненти. За следващите няколко параграфа си представете, че предавате състояние изрично.

Например, вие извиквате този код, когато създавате елемент todo:

За да регистрирате действието и състоянието, можете да промените кода по следния начин:

Това ще даде желания ефект, но не бихте искали да правите това всеки път.

Опит №2: Опаковане на изпращането

Можете да преместите регистрирането във функция:

Можете да го използвате навсякъде вместо обичайния store.dispatch() :

Можем да приключим до тук, но не е много удобно всеки път да импортирате специална функция.

Опит #3: Monkeypatching за Dispatch

Това е по-близо до това, от което се нуждаем! Няма значение откъде изпращаме действието, то гарантирано ще бъде регистрирано. Monkeypatching никога няма да изглежда като правилен ход, но засега можем да живеем с него.

Проблем: Съобщения за грешка.

Какво ще стане, ако искаме да приложимповече от една такава трансформация към dispatch?

Не би ли било полезно, ако всеки път, когато се генерира грешка в резултат на изпращане на някакво действие, можем да я изпратим (грешката), заедно със стека на повикванията, действието, което е причинило грешката, и действителното състояние, до услуга за докладване на грешки като Sentry. В този случай е много по-лесно да се възпроизведе грешката в развитието.

Въпреки това е важно да запазим регистрирането и докладването за грешки отделно. INв идеалния случай искаме да ги получим като различни модули от различни пакети. В противен случай няма да можем да имаме екосистема от такива комунални услуги. (Съвет: Бавно стигаме до дъното на това какво представлява междинният софтуер!)

Ако регистрирането и съобщенията за грешка са отделни помощни програми, тогава те може да изглеждат така:

Но пак не е много добре.

Опит #4: Скриване на Monkeypatching

Monkeypatching е хак. „Заменете всеки метод, който искате“ – какъв вид API е това? Нека разберем същността му. Преди това нашите функции замениха store.dispatch. Ами ако вместо това върнат нова функция за изпращане?

Можем да предоставим помощна функция в рамките на Redux, която може да приложи действителното monkeypatching като част от внедряването:

Можем да използваме този подход, за да приложим множество междинни софтуери:

Това обаче все още е маймунджийство. Фактът, че го крием в библиотеката, не отрича използването на monkeypatching.

Опит #5: Премахнете Monkeypatching

Защо презаписваме изпращането? Разбира се, за да мога да му се обадя по-късно. Но има и друга причина: всеки междинен софтуер има достъп до (и способността да извиква) предишния обвит store.dispatch:

Това е важно за възможността за комбиниране на междинен софтуер във вериги!

Ако applyMiddlewareByMonkeypatching не записва store.dispatch веднага след обработката на първия мидълуер, store.dispatch ще продължи да препраща към оригиналната функция за изпращане. Следователно вторият междинен софтуер също ще бъде свързан с оригиналната функция за изпращане.

Това е моментът, когато „трябва да отидем по-дълбоко“, така че има смисъл да отделим известно време за това. Каскадата от функции изглежда плашеща. Функциите със стрелки от ES6 правят това къри малко повечелесен за очите:

Ето как изглежда междинният софтуер в Redux.

Мидълуерът вече приема функция за изпращане на действие next() и връща друга функция за изпращане на действие, която от своя страна е функцията за изпращане на действие next() за междинния софтуер отляво. Все още е полезно да имате достъп до някои от методите на магазина, като getState(), така че магазинът остава достъпен като аргумент от най-високо ниво.

Опит #6: Най-простото използване на мидълуер

Вместо applyMiddlewareByMonkeypatching(), бихме могли да напишем функция applyMiddleware(), която първо взема окончателната, напълно обвита функция dispatch() и връща копие на магазина, който използва тази функция:

Реализацията на applyMiddleware(), която се доставя с Redux, е подобна на тазино се различава по три важни начина :

Той предоставя на междинния софтуер подмножество от API за съхранение: методите dispatch(action) и getState().

Той използва известен трик, за да се увери, че действието преминава отново през цялата верига на междинния софтуер, включително текущата, ако извикате store.dispatch(action) от вашия междинен софтуер вместо next(action). Това е полезно за асинхронен междинен софтуер, както видяхме по-рано.

За да сте сигурни, че можете да приложите междинния софтуер само веднъж, той работи с createStore(), а не със самия магазин. Вместо (магазин, междинен софтуер) => store , неговият подпис е (. middlewares) => (създаване на магазин) => createStore.

Краен подход

Като се има предвид междинният софтуер, ние току-що написахме:

Ето как можете да го приложите към магазина Redux:

Това е всичко! Сега всяко действие, изпратено до екземпляра на магазина, ще премине през регистратор и crashReporter:

Седем примера

Ако главата википнал от четенето на предишния раздел, представете си какво е било да напиша това. Този раздел е предназначен да отпусне мен и вас и да ви помогне да започнете работата си.

Всяка от функциите по-долу е валиден междинен софтуер на Redux. Те не са еднакво полезни, но поне са еднакво забавни.