Będzie flow i czekanie na akcje. I obserwabla też.

W poprzedniej notce zastanawiałem się, czy nie wywalić możliwości zwracania obserwabli z reducerów i zastąpić je obiektami "efektów", jednak po przemyślaniu uznałem, że zostaje to i to.
  • Mimo wszystko zwracanie obserwabli jest to killer-feature i może przypaść do gustu wielu osobom, nawet jeśli będzie miał pewne trade-offy i nawet jeśli sam będę ostrożny w jego używaniu. A i tak kod do tego ficzera jest już napisany i nie mogę go skasować (ponieważ kod rozwiązujący promisy czy obserwable potrzebny mi jest w innych miejscach, w których coś takiego robię), mógłbym jedynie sztucznie zrobić blokadę na zwracanie tego typu rzeczy z reducera, ale byłoby to bezcelowe.
  • Pisałem, że nie będzie to skalowalne, ale tak w zasadzie to zależy od tego, kto będzie to pisał. Myślę, że jest możliwe napisanie czegoś większego na obserwablach tak, żeby to miało ręce i nogi w większej apce. W zasadzie po części w ogóle zacząłem robić tę libkę. Bo wg mnie obserwable są fajnym konceptem, ale brakuje mi metody na jakąś większą organizację tych obserwabli i integracji z resztą aplikacji.
  • Moje "efekty" też nie będą zawsze serializowalne, zacząłem wymyślać co bardziej zaawansowane efekty, które mogą np. przyjmować funkcję jako argument. Więc to, co zarzucałem podejściu pisania wszystkiego na obserwablach może również dotyczyć moich efektów. No trudno. Może wystarczy jak same akcje będą serializowalne.
Tym niemniej pisanie w sposób wykorzystujący moje obiekty-"efekty" będzie bardziej idiomatyczny w mojej bibliotece i będzie polecany jako ten pierwszy wybór (chociaż i tak jedno drugiemu nie przeszkadza, będzie można łączyć te podejścia).


Ostatnio dorobiłem specjalny efekt fx.flow, który pozwala zapisać interakcje w formie listy przyszłych wartości / efektów. Np. jeśli pobierasz jakieś dane, i chcesz wyświetlić kręcące się kółko na czas pobierania, to będziesz robić po prostu tak:

return fx.flow([
    {data: null, status: 'fetching'},
    () => fetchSomeData('example.json'),
    data => ({ data, status: 'ready' })
]).catch(error => ({ data: null, status: 'error' })

Żadnej zabawy w tworzenie jakichś dodatkowych akcji-helperów, czy innych zabaw. Swoją drogą zawsze się dziwię, jak widzę projekty, w których ktoś, żeby pociągnąć coś z AJAXa robi jakieś dziwne machinacje, tworzy 5 dodatkowych akcji, stałych dla akcji, obsługę tego w reducerze itp.I tak do każdego rodzaju zasobu. Totalna masakra, co ludzie wymyślają.

A przecież nawet korzystając ze standardowego Reduxa możnaby napisać raz ten kod i potem używać w wielu miejscach, zrobić sobie jakieś proste middleware i jakieś proste konwencje.

Anyway, podejście flow pewnie i tak będzie lepsze :) Coś podobnego jest w Mobx, tylko tak jest to robione na generatorach (może dodam też obsługę generatorów, jeśli znajdę use case, którego prosta lista efektów nie będzie mogła obsłużyć)

Poza tym dodałem ostatnio fx.waitFor, które pozwala ci czekać na określone akcje i dopiero potem wykonywać jakieś rzeczy. To się może przydać, jeśli robisz logikę, która jest podzielona na kilka akcji. Np. jeśli otwierasz modal, i w akcji openModal dajesz:

return fx.waitFor(closeModal(), action => action.payload.result);

Tym sposobem kod odpalony w akcji openModal będzie czekał na akcję closeModal i pobierze z niej wyniki.

Czyli logika "jak ma się zachowywać dany ficzer" będzie mogła być napisana w bardziej bezpośredni sposób i w jednym miejscu.

Mam jeszcze więcej pomysłów, póki co je robię i wrzucam na Github (ale jeszcze nie zaktualizowałem pakietu npm). Zacząłem robić też przykład użycia i wyświetlanie interaktywnego kalendarza (komponenty na React, plus Redux, plus Feedbacks). Tutaj macie całą logikę store'a w tym przykładzie: store.js



Komentarze

Popularne posty z tego bloga

Ściemy z ogłoszeń o pracę

Zostać programistą (2) - czy się nadajesz?

Czego się nauczyłem w 2021?