Dowiedz się, czym jest opóźnienie sygnału wejściowego, i poznaj techniki, które pozwalają go zmniejszyć i zwiększyć interaktywność.
Interakcje w internecie to skomplikowane zjawisko, a w przeglądarce do ich wywoływania zachodzi różnego rodzaju aktywność. Wszystkie mają jednak wspólną cechę: przed uruchomieniem wywołań zwrotnych zdarzeń występuje opóźnienie w dostarczonej informacji. Z tego przewodnika dowiesz się, czym jest opóźnienie w rejestracji danych wejściowych i jak je zminimalizować, aby interakcje z witryną przebiegały szybciej.
Co to jest opóźnienie danych wejściowych?
Opóźnienie przy pierwszym działaniu to okres od momentu, gdy użytkownik po raz pierwszy wchodzi w interakcję ze stroną (np. klika ekran, klika myszką lub naciska klawisz) do chwili, gdy zaczynają się wywołania zwrotne zdarzenia dotyczące interakcji. Każda interakcja rozpoczyna się z pewnym opóźnieniem.
Część opóźnienia danych wejściowych jest nieunikniona: rozpoznanie zdarzenia wejściowego i przekazanie go do przeglądarki wymaga trochę czasu. Jednak ta część opóźnienia danych wejściowych jest często niezauważalna, a inne czynniki dzieją się na samej stronie, które mogą powodować tak duże opóźnienia danych wejściowych, że powodują problemy.
Jak wziąć pod uwagę opóźnienie sygnału wejściowego
Ogólnie rzecz biorąc, każdą część interakcji należy skrócić do minimum, aby zwiększyć szanse witryny na osiągnięcie „dobrego” progu wartości danych wskaźnika Interakcja do kolejnego wyrenderowania (INP) niezależnie od urządzenia użytkownika. Kontrolowanie opóźnienia wprowadzania danych to tylko jeden z elementów, które pozwalają osiągnąć ten próg.
Dlatego warto dążyć do jak najkrótszego opóźnienia wejścia, aby osiągnąć „dobry” próg INP. Pamiętaj jednak, że nie można całkowicie wyeliminować opóźnień w składaniu danych. Jeśli unikniesz nadmiernego obciążania wątku głównego, gdy użytkownicy próbują wchodzić w interakcję ze stroną, opóźnienie danych wejściowych powinno być wystarczająco krótkie, aby uniknąć problemów.
Jak zminimalizować opóźnienie sygnału wejściowego
Jak wspomnieliśmy wcześniej, pewnego opóźnienia sygnału wejściowego nie da się uniknąć, ale z drugiej strony można uniknąć takiego opóźnienia. Oto kilka rzeczy, które warto wziąć pod uwagę, jeśli masz duże opóźnienia w przesyłaniu danych.
Unikaj powtarzających się zegarów, które uruchamiają nadmierne obciążenie wątku głównego.
W JavaScript istnieją 2 funkcje zegara, które mogą przyczyniać się do opóźnienia wprowadzania danych: setTimeout
i setInterval
. Różnica między nimi polega na tym, że setTimeout
planuje wywołanie zwrotne po określonym czasie. setInterval
natomiast planuje wywołanie zwrotne co n milisekund w nieskończoność lub do momentu zatrzymania licznika przy użyciu clearInterval
.
setTimeout
sam w sobie nie jest problemem, a nawet może pomóc w unikaniu długich zadań. Zależy to jednak od czasu, w jakim nastąpiło przekroczenie limitu czasu, oraz od tego, czy użytkownik próbuje wchodzić w interakcję ze stroną, gdy wykonywane jest wywołanie zwrotne po przekroczeniu limitu czasu.
Poza tym funkcja setTimeout
może być uruchamiana w pętli lub rekurencyjnie, gdzie działa podobnie jak setInterval
, lepiej jednak nie planować kolejnej iteracji, dopóki nie zostanie zakończona. Oznacza to, że za każdym razem, gdy wywoływana jest funkcja setTimeout
, pętla zwraca kontrolę głównemu wątkowi. Pamiętaj jednak, aby wywołanie zwrotne tej funkcji nie wykonywało zbyt wielu operacji.
setInterval
wywołuje wywołanie zwrotne w określonym odstępie czasu, przez co znacznie częściej może zakłócać interakcje. W odróżnieniu od pojedynczego wywołania funkcji setTimeout
, które jest jednorazowym wywołaniem, które może przeszkadzać w interakcjach z użytkownikiem, setInterval
jest wywoływane wielokrotnie, co znacznie zwiększa prawdopodobieństwo, że będzie przeszkadzać w interakcjach, zwiększając tym samym opóźnienie wprowadzania danych.
Jeśli zegary występują w kodzie własnym, masz nad nimi kontrolę. Zastanów się, czy ich potrzebujesz, i spróbuj zminimalizować ich liczbę. Jednak liczniki czasu w skryptach innych firm to zupełnie inna historia. Często nie masz kontroli nad tym, co robi skrypt zewnętrzny. Rozwiązywanie problemów z wydajnością kodu zewnętrznego często wymaga współpracy z osobami zainteresowanymi, aby ustalić, czy dany skrypt zewnętrzny jest niezbędny. Jeśli tak, skontaktuj się z dostawcą skryptu, aby dowiedzieć się, jak rozwiązać problemy z wydajnością, które mogą być przez niego powodowane.
Unikaj długich zadań
Jednym ze sposobów na zmniejszenie opóźnień w przyjmowaniu danych jest unikanie długich zadań. Jeśli wątek główny jest zbyt obciążony i blokuje interakcje, to spowoduje to opóźnienie wprowadzania danych, zanim długie zadania zostaną ukończone.
Oprócz minimalizowania ilości pracy wykonywanej w ramach zadania (zawsze staraj się wykonywać jak najmniej pracy w wątku głównym) możesz zwiększyć szybkość reakcji na dane wejściowe użytkownika, dzielisz długie zadania.
Pamiętaj o pokrywaniu się interakcji
Szczególnie trudne może być zoptymalizowanie INP, jeśli masz interakcje, które się na siebie nakładają. Nakładanie się interakcji oznacza, że po interakcji z jednym elementem wchodzisz w interakcję z innym elementem na stronie, zanim pierwotna interakcja zdąży wyrenderować kolejny kadr.
Źródła nakładających się interakcji mogą być tak proste jak użytkownicy wykonujący wiele interakcji w krótkim czasie. Może się tak zdarzyć, gdy użytkownicy wpisują tekst w polach formularza, w których w bardzo krótkim czasie może wystąpić wiele interakcji z klawiaturą. Jeśli praca nad kluczowym zdarzeniem jest szczególnie kosztowna, np. w przypadku pól autouzupełniania, w których wysyłane są żądania sieci do zaplecza, masz kilka opcji:
- Rozważ debounce danych wejściowych, aby ograniczyć liczbę wywołań funkcji zwrotnej zdarzenia w danym przedziale czasu.
- Używaj
AbortController
do anulowania wychodzących żądańfetch
, aby wątek główny nie był przeciążony podczas obsługi wywołań zwrotnychfetch
. Uwaga: właściwościsignal
instancjiAbortController
można też używać do przerywania zdarzeń.
Innym źródłem zwiększonego opóźnienia danych wejściowych z powodu nakładających się interakcji mogą być drogie animacje. W szczególności animacje w języku JavaScript mogą uruchamiać wiele wywołań requestAnimationFrame
, które mogą przeszkadzać w interakcjach użytkownika. Aby tego uniknąć, używaj animacji CSS, gdy tylko to możliwe, aby uniknąć kolejkowania potencjalnie kosztownych klatek animacji. Pamiętaj jednak, aby nie używać nieskomponowanych animacji, ponieważ animacje powinny być renderowane głównie na wątkach procesora graficznego i składania, a nie na wątku głównym.
Podsumowanie
Opóźnienia danych wejściowych mogą nie odpowiadać większość czasu potrzebnego na interakcję, ale trzeba pamiętać, że każdy etap interakcji zajmuje czas, który można skrócić. Jeśli zauważysz długi czas reakcji na dane wejściowe, możesz go skrócić. Unikanie powtarzających się wywołań przez timer, dzielenie długich zadań i świadomość potencjalnego nakładania się interakcji mogą pomóc w zmniejszeniu opóźnienia wprowadzania danych, co prowadzi do szybszej interakcji z użytkownikami witryny.
Baner powitalny z filmu Unsplash, Erik Mclean.