Moduł9 - Zajęcia 17 - Minutniki i czas
Minutniki i czas
Cały kod JavaScript jest wykonywany przez procesor komputera. Kod, który do tej pory napisaliśmy, był synchroniczny, czyli zajmował procesor przez cały czas jego wykonywania. Przez to na przykład szybkość pętli do iteracji po tablicy zależy od szybkości procesora.
Istnieją operacje, które wchodzą w interakcję ze światem zewnętrznym. Przykładem będzie wymiana danych z serwerem przez sieć, co jest znacznie wolniejsze niż pobieranie ich z pamięci. Jeżeli takie operacje są przetwarzane synchronicznie, procesor musiałby czekać bezczynnie, podczas gdy żądanie sieciowe do serwera jest w toku, zamiast wykonywać inne instrukcje.
Kod synchroniczny jest wykonywany sekwencyjnie, każda instrukcja czeka na wykonanie poprzedniej. Gdy wywołujesz funkcję, która wykonuje długotrwałą akcję, zatrzymujesz program na cały czas jego wykonywania. Oznacza to, że w modelu programowania synchronicznego wszystko dzieje się po kolei.
Wyobraź sobie kolejkę za biletami na dworcu. Nie możesz zacząć kupować biletu, dopóki nie kupi go osoba przed tobą. Również osoby stojące za tobą nie mogą zacząć kupować biletów, dopóki Ty nie kupisz swojego.
W kodzie asynchronicznym wiele operacji może być wykonywanych jednocześnie. W tym modelu, żądanie sieciowe do serwera nie zatrzyma programu, będzie on kontynuował wykonywanie innych operacji. Po zakończeniu działania żądania program jest o tym informowany i uzyskuje dostęp do wyniku (np. danych z serwera).
Wyobraź sobie obiad w restauracji. Ty i inni goście zamawiacie jedzenie. Nie musisz czekać, aż im przyniosą jedzenie przed złożeniem swojego zamówienia. Podobnie inni odwiedzający nie muszą czekać, aż otrzymasz danie i zjesz, zanim będą mogli zamówić. Każdy otrzyma swoje danie, gdy tylko zostanie przygotowane.
Rozważmy różnicę w przykładzie, w którym program wysyła do serwera dwa żądania sieciowe, a następnie przetwarza ich wynik. Operacje 1 i 2 to funkcje, które wysyłają żądania do serwera, a 3,4 i 5 to dowolny inny synchroniczny kod, który znasz.
W modelu synchronicznym wszystko jest jasne i efekt jest raczej smutny - wszystkie operacje blokują wykonanie kolejnych aż do ich zakończenia. Jeśli operacje 3-5 przetwarzają kliknięcia użytkownika, interfejs po prostu zawiesi się, dopóki wyniki żądań 1-2 nie zostaną zakończone i przetworzone
Załóżmy, że użytkownik opublikował komentarz (co realizuje się przez żądanie sieciowe) i jednocześnie chciał otworzyć pasek boczny z najnowszymi wiadomościami. Po kliknięciu wyślij komentarz, interfejs zawiesi się i nie będzie reagował na jego działania, dopóki wynik wysłania komentarza nie nadejdzie z serwera. Oczywiście jest to niedopuszczalne.
W modelu asynchronicznym rozpoczęcie żądania sieciowego powoduje rozwidlenie, czyli uruchomienie żądania i wynikiem jego przetworzenia są różne akcje. Podczas wykonywania żądania program kontynuuje działanie i wykonuje inny kod. Gdy żądanie sieciowe zostanie zakończone, program może rozpocząć przetwarzanie jego wyniku, gdy tylko będzie wolny. Oznacza to, że użytkownik opublikował komentarz i mógł od razu otworzyć pasek boczny z najnowszymi wiadomościami, nie czekając na odpowiedź z serwera.
W jednostce czasu można wykonać tylko jedną operację, ponieważ JavaScript jest jednowątkowy. Programowanie asynchroniczne jest osiągane przez odroczone wywołania funkcji, w których inicjowanie operacji asynchronicznej i przetwarzanie jej wyniku to różne akcje.