post-image
28.09.2020

Async / await – nie takie fajne jak myślisz – prostota syntaxu kosztem użytkownika

Dzisiaj chciałbym poruszyć pewien temat, który pewnie nie jest wszystkim znany, a jeśli już jest znany to nie znają go na tyle, aby uświadomić sobie, że ma często więcej wad niż zalet

Będę dzisiaj kodzić w promisach i w async / await i liczyć czas wykonywania się wielu promisów. Także zaczynamy!

Tym postem chciałbym pokazać, że pisanie kodu z async / await nie jest optymalne w przypadku więcej niż jednej promisy i stosowanie async / await w przypadku realnych przypadków może spowolnić Twój kod N-razy (N to liczba promis w funkcji)

Cały przykład ma pokazać analogiczną sytuację, w której np na początku działania apki, robimy 3 zapytania do api np po posty, produkty i komentarze i chcemy zaprezentować aplikację. Symulacja zapytania rozpatruje tylko pozytywny przypadek (status 200 w response)

Zacznijmy od napisania sobie prostego poletka testowego w kilkoma promisami:

Tworzę sobie funkcję generującą promisę, która trwa 1 sekundę i przepycham definicję tej funkcji do arraya testowego, aby wywołać to nie od razu tylko w miejscu, w którym chcę to wywołać – czyli na inicjalizacji naszej zmyślonej „apki”

Jako benchmark weźmiemy sobie Promise.all:

ostatni element arraya result to czas wykonania w milisekundach

Czas wykonania Promise.all to niewiele ponad 1 sekundę

Czyli wszystkie 3 promisy zostały wystartowane jednocześnie i skończyły się prawie jednocześnie – jest to najlepszy, możliwy scenariusz

Teraz zbudujemy Promise.all od zera w oparciu o podstawową wiedzę o promisach:

ostatni element arraya result to czas wykonania w milisekundach

Czas wykonywania naszej metody Promise.all opartej o wiedzę z promisów to również niewiele ponad sekundę (1ms mniej niż Promise.all to błąd pomiaru):

Czyli znów wszystkie 3 promisy zostały wystartowane jednocześnie i skończyły się prawie jednocześnie – jest to kolejny najlepszy, możliwy scenariusz – jednak dla uproszczenia polecam stosować Promise.all

A teraz „król parkietu” – async / await

ostatni element arraya result to czas wykonania w milisekundach

Czas wykonywania naszej metody Promise.all opartej o async / await to aż 3 sekundy!! czyli 3 razy dłużej. W przypadku 4 zapytań do api będzie to 4x dłużej

Czyli przez Twoją chęc zastosowania async / await kazałeś użytkownikowi aplikacji czekać 3 razy dłużej niż to realnie koniecznie

Tak wiem – zaraz ktoś się przyczepi, że to przypadek testowy albo, że można to inaczej napisać – tutaj chodziło głównie o pokazanie pewnego schematu

Dlatego chciałem też pokazać przypadek, który bardzo często widzę w jakichś projektach do portfolio, albo (o zgrozo…) na tutorialach… commit mi się cofa jak widzę, że tutorial obejrzało 10-15 tysięcy potencjalnych programistów i nauczyło się takich głupot

Więc odzwierciedlając przypadek stricte tutorialowy, robimy 3 zapytania do api z async / await i try / catch, aby wychwycić ewentualne błędy

I znów powtarza się ta sama sytuacja – 3 zapytania 3 sekundy czekania użytkownika na załadowanie aplikacji

3 zdania podsumowania:

  • im mniej async / await w Twoim kodzie tym (prawdopodobnie) lepiej dla użytkownika
  • jeśli stosujesz async / await to pamiętaj, aby w zakresie funkcji była tylko jedna promisa, która „awaitujesz”, bo każda kolejna powoduję wydłużenie działania Twojego kodu
  • nie wszystko co widzisz na popularnych tutorialach to optymalny kod i należy powtarzać to w swoim projekcie

EDIT – Sugestia zakończenia od Bartka Banacha:

Tak więc radzę na to uważać i używać Promise.all jeśli chcemy wykonać kilka zapytań do api jednocześnie, bo async / await wcale jednoczesności nie zapewnia, a tylko upraszcza składnię w kodzie dla programisty

Do następnego commita!

Do następnego commita!

Jeśli dowiedziałeś czegoś konkretnego z tego posta, to postaw mi kawę, która zasili kolejne posty z materiałami dla programistów!

coffee
coffee

Dołącz do listy mailingowej Gladiatorów Javascriptu!

Będziesz otrzymywać linki do zajęć z Gladiatorami, przydatne do nauki artykuły oraz informacje odnośnie aktualizacji zbiorów.

 
Twoj adres email
Wyślij wiadomość
* Zapisując się do newslettera zgadzasz się na przetwarzanie swoich informacji osobowych zgodnie z naszą Polityką Prywatności.