Czy kiedykolwiek musiałeś uruchomić kod w przeglądarce, który trwał tak długo, aby Twoja aplikacja przestała odpowiadać przez jakiś czas? Dzięki robotnikom internetowym HTML5 nigdy więcej tego nie doświadczysz.
Webworkery umożliwiają oddzielenie długo działającego kodu i uruchomienie go niezależnie od innego kodu działającego na stronie. Dzięki temu interfejs użytkownika jest responsywny, nawet podczas złożonych operacji.
Kim są pracownicy sieci Web?
Tradycyjnie JavaScript jest językiem jednowątkowym. Oznacza to, że nic innego nie może działać, gdy działa jeden fragment kodu. Na przykład, jeśli masz kod próbujący animować element DOM, kod próbujący zmienić zmienną musi poczekać na zakończenie animacji, zanim będzie można ją uruchomić.
Webworkery to pliki JavaScript, które są wykonywane w osobnym wątku bez bezpośredniego dostępu do DOM.
Jednym ze sposobów myślenia o robotnikach sieciowych jest to, że są to fragmenty kodu, których uruchomienie zajmuje dużo czasu, więc przekazujesz je przeglądarce do wykonania w tle. Ponieważ ten kod działa teraz w tle, nie ma wpływu na JavaScript odpowiedzialny za twoją stronę internetową.
Jako efekt uboczny, nie może już bezpośrednio wchodzić w interakcję z resztą kodu, więc pracownicy sieciowi nie mają dostępu do DOM. Jednak wiele innych interfejsów API przeglądarki jest nadal dostępnych, w tym interfejsy API WebSocket i Fetch.
Pracownicy sieci Web nie są jednak całkowicie odizolowani od głównego wątku. Gdy pracownik musi komunikować się z głównym wątkiem, może wysłać wiadomość, a główny wątek może w odpowiedzi wysłać własną wiadomość.
Dlaczego pracownicy sieci Web?
Przed robotami sieciowymi jedynym sposobem uruchamiania JavaScript, który wymagał dużo czasu w przeglądarce, było:
- Zaakceptuj, że strona przez jakiś czas nie będzie odpowiadać.
- Złam ten kod na asynchroniczne porcje.
Ponieważ niereagująca strona jest zwykle zła dla użytkownika, możesz wybrać opcję asynchroniczną. Pisanie kodu w ten sposób oznacza podzielenie go na mniejsze części, które przeglądarka może uruchomić, gdy nie obsługuje interfejsu użytkownika. Kawałki muszą być na tyle małe, że jeśli interfejs użytkownika wymaga aktualizacji, przeglądarka może zakończyć wykonywanie bieżącego kawałka i zająć się interfejsem użytkownika.
Webworkerzy zostali dodani do HTML5, aby zaoferować lepsze rozwiązanie tego problemu. Zamiast zmuszać cię do kreatywności z kodem asynchronicznym, pozwalają ci wyraźnie oddzielić funkcję do uruchomienia we własnym izolowanym wątku.
Ułatwiło to programistom pisanie takiego kodu, a także poprawiło wrażenia użytkownika.
Przypadki użycia dla pracowników internetowych
Każda aplikacja, która wymaga dużej ilości obliczeń po stronie klienta, może skorzystać na robotach sieciowych.
Załóżmy na przykład, że Twoja aplikacja chce wygenerować raport użytkowania i przechowuje wszystkie dane na kliencie z obawy o prywatność.
Aby wygenerować ten raport, aplikacja internetowa musi pobrać dane, wykonać na nich obliczenia, uporządkować wyniki i przedstawić je użytkownikowi.
Gdybyś próbował to zrobić w głównym wątku, użytkownik byłby całkowicie niezdolny do korzystania z aplikacji podczas przetwarzania danych przez aplikację. Zamiast tego możesz przenieść część lub całość tego kodu do robota sieciowego. Pozwala to użytkownikowi na dalsze korzystanie z aplikacji podczas wykonywania obliczeń.
Jak korzystać z Web Workerów w JavaScript
The Web Worker API definiuje sposób korzystania z pracowników sieci Web. Korzystanie z tego interfejsu API wiąże się z utworzeniem obiektu Worker za pomocą konstruktora Worker w następujący sposób:
niech nowyPracownik = Pracownik('pracownik.js');
The Pracownik Konstruktor przyjmuje nazwę pliku JavaScript jako swój parametr i uruchamia plik w nowym wątku. Zwraca obiekt Worker, aby umożliwić interakcję głównego wątku z wątkiem roboczym.
Pracownicy wchodzą w interakcję z głównym wątkiem, przesyłając wiadomości tam iz powrotem. Używasz Wyślij wiadomość funkcja do wysyłania zdarzeń między pracownikiem a głównym wątkiem. Użyj onmessage detektor zdarzeń, aby nasłuchiwać wiadomości od drugiej strony.
Oto przykład kodu. Po pierwsze, główny wątek może wyglądać tak:
wynajmować pracownik = Nowy Pracownik('pracownik.js')
pracownik.postWiadomość('Hej!')
pracownik.onmessage = funkcjonować(mi) {
konsola.log('Wątek pracownika mówi', e.dane)
}
Ten główny wątek tworzy obiekt pracownika z pliku worker.js, a następnie wysyła do niego wiadomość za pomocą pracownik.postWiadomość. Następnie definiuje detektor zdarzeń, podobny w koncepcji do Odbiornik zdarzeń DOM. Zdarzenie zostanie wywołane za każdym razem, gdy pracownik wyśle wiadomość z powrotem do głównego wątku, a program obsługi zarejestruje wiadomość pracownika w konsoli.
Kod wewnątrz pracownika (worker.js) ma jedno zadanie:
wiadomość = funkcjonować(mi) {
wynajmować wiadomość = e.dane;
konsola.log('Główny wątek powiedział', wiadomość);
Wyślij wiadomość('Cześć!')
}
Nasłuchuje wszystkich komunikatów wysłanych z głównego wątku, rejestruje komunikaty w konsoli i wysyła komunikat zwrotny z powrotem do głównego wątku.
Wszystkie komunikaty w tym przykładzie były ciągami, ale nie jest to wymagane: możesz wysłać prawie każdy typ danych jako komunikat.
Pracownicy, których do tej pory widziałeś, nazywani są oddanymi pracownikami. Możesz uzyskać do nich dostęp tylko z pliku, w którym je utworzyłeś (są do tego dedykowane). Współdzieleni pracownicy są odwrotnością: mogą odbierać wiadomości z wielu plików i wysyłać je do wielu plików. Pracownicy współdzieleni są koncepcyjnie tacy sami jak pracownicy dedykowani, ale trzeba ich używać nieco inaczej.
Spójrzmy na przykład. Zamiast używać konstruktora Worker, każdy plik, który chce użyć współdzielonego pracownika, musi utworzyć obiekt roboczy za pomocą Współdzielony pracownik():
wynajmować współdzielonyPracownik = Nowy SharedWorker('pracownik.js')
Na tym jednak różnice się nie kończą. Aby plik mógł wysłać lub odebrać wiadomość od współdzielonego pracownika, musi to zrobić, uzyskując dostęp do Port obiekt, zamiast robić to bezpośrednio. Oto jak to wygląda:
sharedWorker.port.postMessage('Cześć!')
sharedWorker.port.onMessage = funkcjonować(mi) {
konsola.log('Współdzielony pracownik wysłał', e.dane);
}
Musisz również użyć obiektu portu wewnątrz pracownika:
onconnect = funkcjonować(mi) {
stały port = e.porty[0];
port.onmessage = funkcjonować(mi) {
konsola.log('Wiadomość odebrana', e.dane)
port.postMessage('Witam!');
}
}
The onconnect słuchacz uruchamia się za każdym razem, gdy następuje połączenie z portem (gdy onmessage detektor zdarzeń jest ustawiony w głównym wątku).
Kiedy tak się dzieje, kod pobiera port, do którego właśnie podłączono ze zdarzenia connect, i zapisuje go w zmiennej. Następnie kod rejestruje onmessage odbiornik na obiekcie portu. Następnie kod rejestruje komunikat w konsoli i używa portu do wysłania komunikatu z powrotem do głównego wątku.
Web Workers poprawiają wrażenia użytkownika
Webworkers to wątki JavaScript, które umożliwiają uruchamianie złożonych i długotrwałych fragmentów kodu w tle. Ten kod pozwoli uniknąć blokowania interfejsu użytkownika. Korzystanie z pracowników sieci Web znacznie ułatwia pisanie tego rodzaju kodu i poprawia komfort użytkowania aplikacji. Korzystając z interfejsu Web Worker API, można tworzyć pracowników sieci Web i komunikować się z nimi.