Promisy są aktualnie podstawowym sposobem radzenia sobie z asynchronicznym kodem w JavaScript. Pojawiają się prawie w każdym trochę bardziej zaawansowanym kawałku kodu. Czasem jest ich choćby aż za dużo. Jak więc sobie radzić z dużą ilością Promisów w aplikacji?
Javascript-exercises
Jeśli już teraz wiesz, jakie sobie z tym poradzić, to sprawdź swoje umiejętności w specjalnie przygotowanych ćwiczeniach z JavaScript. Stworzyłem repozytorium z testami, które mają pomóc w nauce i sprawdzić wiedzę. Sprawdź swoją wiedzę już teraz
Promise hell
Jaki jest problem z Promise'ami? W końcu rozwiązały słynny problem callback hell (o którym poczytacie więcej we wpisie o asynchroniczności w JS). Ale pojawia się za to inny problem tzw.: promise hell. Występuje w sytuacji gdzie mamy kilka zależnych od siebie zapytań lub też konstruujemy odpowiedź na podstawie danych z kilku źródeł. Możemy wtedy albo wykorzystywań .then() (ale przypomni to trochę callback hell) albo skorzystać z async/await (ale wtedy tworzy nam się kod synchroniczny). Jak więcej lepiej to zrobić?
Promise.all()
Na sam początek moja ulubiona i często wykorzystywana metoda - Promise.all(). Przyjmuje jako parametr tablicę Promise'ów i zwraca Promise'a. Po rozwiązaniu będzie zawierał on tablicę wartości dla wszystkich rozwiązanego Promise'a wewnątrz. Będzie on rozwiązany poprawnie, jeżeli wszystkie wartości przekazane jako argument rozwiążą się poprawnie. jeżeli na którymś Promise wystąpi błąd, to wykonywanie funkcji zostaje wstrzymane i jest zwrócony błąd tzw.: fail-fast. Bardzo często wykorzystuję to do pobierania danych o kilku elementach jednocześnie np.: z profilu użytkownika dostaję informację o id przeczytanych książek i chcąc wyświetlić informacje o nich, trzeba pobrać dane książki z innego endpointa.
Promise.allSettled()
Następną funkcją jest Promise.allSettled(). Podobnie jak poprzednia funkcja, pozwala uzyskać wartości przekazanych Promise'ów po tym, jak wszystkie się poprawnie rozwiążą. To, co je różni to sposób zachowania, gdy wystąpi błąd. Promise.allSettled nie przerywa działania podczas wystąpienia błędu. Jako wynik dostajemy informację, jak każdy przekazany w argumencie Promise się rozwiązał oraz z jaką wartością. Dzięki temu choćby jak jedna operacja się nie powiedzie, to z pozostałych dostaniemy informacje. Tutaj ważna uwaga - dostajemy tablicę obiektów {status, value} więc do adekwatnych wartości musimy się dopiero dostać.
Promise.race()
Kolejną ciekawą funkcją jest Promise.race(), której nazwa zdradza już sposób zachowania. Przekazujemy jako argument ponownie tablicę Promise'ów. Jako wynik dostajemy pierwszą wartość, która się rozwiąże - nie ważne czy to będzie poprawne rozwiązanie, czy też wystąpi błąd.
Promise.any()
Na sam koniec rozszerzenie poprzedniej funkcji, czyli Promise.any(). Jako wynik jest zwracana pierwsza wartość, która rozwiąże się poprawnie. Oznacza to, iż choćby jeżeli jakiś błąd wystąpił szybciej, to zostanie zignorowany i funkcja będzie czekać na poprawną wartość. Można by to wykorzystać, jeżeli mamy bazę danych oraz cache i chcemy otrzymać poprawne dane z jednego lub drugiego miejsca.
Niestety nie jest to jeszcze oficjalna funkcja, ale wejdzie do standardu w 2021.