Czy jest jakiś powód, aby używać synchronicznego XMLHttpRequest?


88

Wydaje się, że prawie każdy wykonuje żądania asynchroniczne za pomocą XMLHttpRequest, ale oczywiście fakt, że istnieje możliwość wykonywania żądań synchronicznych, wskazuje, że może to być uzasadniony powód. Więc jaki może być ten ważny powód?


1
To całkiem dobre pytanie! Nie sądzę, żeby odpowiedź była bardzo interesująca, ale mimo wszystko świetne pytanie. Czy próbowałeś wykonać połączenie synchroniczne, aby zobaczyć, co się stanie?
Tad Donaghe

3
Synchroniczne połączenia blokują przeglądarkę, co prowadzi do strasznych wrażeń użytkownika. Stąd moje pytanie. Nie mogłem wymyślić żadnego dobrego powodu, aby go użyć.
Darrell Brogdon

2
Półpoważna odpowiedź: może po prostu wypełnić rozdział, który pojawia się przed asynchronicznymi żądaniami w dowolnej książce JavaScript, którą czytasz.
Ben James,

Osobiście chciałbym użyć synchronicznego AJAX do opakowywania wielu wywołań funkcji po stronie serwera bez konieczności pisania żądania dla każdego wywołania.
Paul Ishak

uruchamianie kodu lokalnie, szczególnie w przypadku wewnętrznych struktur programistycznych i narzędzi.
user2800679

Odpowiedzi:


25

Myślę, że mogą stać się bardziej popularne w miarę postępu standardów HTML 5. Jeśli aplikacja internetowa ma dostęp do pracowników internetowych, mógłbym przewidzieć, że programiści będą korzystali z dedykowanego pracownika internetowego do wykonywania synchronicznych żądań, aby, jak powiedział Jonathan, upewnić się, że jedno żądanie wystąpi przed drugim. Przy obecnej sytuacji jednego wątku jest to mniej niż idealny projekt, ponieważ blokuje się do zakończenia żądania.


16
Zakładam, że miał na myśli „pracowników sieci”
evilpie

Myślę, że destylowany punkt. W wątku interfejsu użytkownika Utwórz wątek lub zadanie asynchroniczne. Jeśli jest już w wątku, w większości przypadków użyj zsynchronizowanego. Wątki są dużo bardziej „przyjazne dla bloków”
HaMMeReD,

To stara odpowiedź, ale ten komentarz dotyczy nawet wtedy, jeszcze przed HTML5, przeglądarki przewidywały 2 wątki do wysyłania zapytań. Napisałem skrypt puli połączeń, aby korzystać z obu, ponieważ nawet przy żądaniu asynchronicznym, przy jednym połączeniu, można było powiązać przeglądarkę. Wykorzystanie obu pozwala na przepychanie / przeciąganie większej ilości danych przez linię; ale iirc, myślę, że żądania synchronizacji nadal wiązały przeglądarkę.
vol7ron

Firefox (i prawdopodobnie wszystkie przeglądarki inne niż IE) nie obsługuje asynchronicznego XHR timeOut. WebWorkers HTML5 obsługują limity czasu. Tak więc możesz chcieć zawinąć żądanie synchronizacji XHR do WebWorker z limitem czasu, aby zaimplementować asynchroniczne XHR z zachowaniem limitu czasu.
Dmitry Kaigorodov

1
-1. To nie jest duża odpowiedź, a cała dyskusja na temat wątków tylko zagmatwa sprawę. Poniższa odpowiedź Sami jest w rzeczywistości znacznie lepsza.
Stijn de Witt

30

Synchroniczne XHR są przydatne do zapisywania danych użytkownika. Jeśli obsługujesz beforeunloadzdarzenie, możesz przesłać dane na serwer, gdy użytkownik zamyka stronę.

Gdyby zostało to zrobione przy użyciu opcji async, strona może zostać zamknięta przed zakończeniem żądania. Wykonanie tej czynności synchronicznie gwarantuje ukończenie lub niepowodzenie żądania w oczekiwany sposób.


4
Edytowane: Zdaję sobie sprawę, że po prostu zrzucasz txt od leniwego użytkownika HN, ale trochę czasu na jego ładnie sformułowanie jest doceniane tutaj, na SO.
Frank Krueger

Ale w rzeczywistości jest to jedyny ważny powód, jaki widziałem do tej pory.
Stijn de Witt

@Frank Krueger Co to jest HN?
Douglas odbył się

1
@DouglasHeld Witryna o nazwie Hacker News pod adresem news.ycombinator.com
Sami Samhuri

13

Aktualizacja:

Poniższe sugeruje - ale nie udało się dostarczyć - że wraz z pojawieniem się lepszej asynchronicznej obsługi żądań, naprawdę nie ma powodu, aby używać żądań synchronicznych, chyba że celowo blokuje użytkownikom możliwość robienia czegokolwiek do momentu zakończenia żądania - brzmi złośliwie: )

Chociaż może to zabrzmieć źle, mogą się zdarzyć sytuacje, w których ważne jest, aby żądanie (lub seria żądań) wystąpiło przed opuszczeniem strony przez użytkownika lub przed wykonaniem czynności - blokowanie wykonania innego kodu (np. Blokowanie przycisku Wstecz) ewentualnie zmniejszyć liczbę błędów / konserwacji źle zaprojektowanego systemu; To powiedziawszy, nigdy nie widziałem tego na wolności i podkreślam, że należy tego unikać.

Biblioteki, podobnie jak obietnice , udają synchroniczność, łącząc procesy za pomocą wywołań zwrotnych. Odpowiada to większości potrzeb programistycznych, w których pożądane jest uporządkowanie zdarzeń nieblokujących, które umożliwiają przeglądarkom zachowanie responsywności dla użytkownika (dobry UX).

Jak stwierdzono w dokumentacji Mozilli, są przypadki, w których musisz używać żądań synchronicznych; jednak wymieniono również obejście, które w takich przypadkach używa sygnału nawigacyjnego (niedostępnego w przeglądarce IE / Safari). Chociaż jest to eksperymentalne, jeśli kiedykolwiek osiągnie akceptację standardów, może wbić gwóźdź do trumny z synchronicznymi żądaniami.


Chcesz wykonywać połączenia synchroniczne w dowolnym przetwarzaniu podobnym do transakcji lub wszędzie tam, gdzie wymagana jest dowolna kolejność operacji.

Na przykład, powiedzmy, że chcesz dostosować zdarzenie, aby wylogowało Cię po odtworzeniu piosenki. Jeśli operacja wylogowania nastąpi jako pierwsza, utwór nigdy nie zostanie odtworzony. Wymaga to synchronizacji żądań.

Innym powodem może być praca z usługą sieciową, zwłaszcza podczas wykonywania operacji matematycznych na serwerze.

Przykład: serwer ma zmienną o wartości 1.

 Step (1) Perform Update: add 1 to variable
 Step (2) Perform Update: set variable to the power of 3
 End Value: variable equals 8

Jeśli Krok (2) występuje jako pierwszy, to wartość końcowa wynosi 2, a nie 8; dlatego kolejność operacji ma znaczenie i konieczna jest synchronizacja.


Bardzo rzadko zdarza się, że połączenie synchroniczne może być uzasadnione we wspólnym przykładzie z rzeczywistego świata. Być może po kliknięciu zaloguj się, a następnie kliknięciu części witryny, która wymaga zalogowania użytkownika.

Jak powiedzieli inni, spowoduje to związanie przeglądarki, więc trzymaj się z dala od niej, gdzie możesz.

Jednak zamiast wywołań synchronicznych użytkownicy często chcą zatrzymać aktualnie ładowane zdarzenie, a następnie wykonać inną operację. W pewnym sensie jest to synchronizacja, ponieważ pierwsze zdarzenie kończy się przed rozpoczęciem drugiego. Aby to zrobić, użyj metody abort () na obiekcie połączenia xml.


1
Myślę, że to powinna być prawdziwa odpowiedź

3
@Zack: to dobry przykład, jednak prawdopodobnie możesz zrobić to samo z wywołaniami asynchronicznymi w zależności od zdarzenia, które je wywołuje.
vol7ron

3
+1 Istnieje ważny przypadek, że logiczne warunki wyścigu mogą wynikać z asynchronicznych żądań serwera ... Jednak rozwiązaniem nie musi być synchronizacja. O ile żądania nie są obsługiwane przez pracownika sieci Web, lepiej byłoby napisać warstwę transportową, która numerowałaby żądania, a następnie zapewniała obsługę operacji w kolejności identyfikatorów żądań.
Roy Tinker

3
-1 Przetwarzanie transakcji jest doskonałym przykładem, w którym musisz użyć gwarancji, że coś się nie powiedzie lub powiedzie - tylko dlatego, że polecenie jest synchroniczne, nie oznacza, że ​​pierwsze żądanie się powiodło ... polegasz na odpowiedzi, która ci to mówi. W tym przykładzie możesz wykonać drugie żądanie tylko z poziomu procedury obsługi wyników pierwszego żądania - w takim przypadku oba równie dobrze mogą być asynchroniczne.
Mathew

2
@Mathew: jest to prawdą tylko wtedy, gdy proces podobny do transakcji zależy od wyniku działania przed nim. Jeśli masz przycisk, który tworzy nowy obiekt (pobrany z serwera) na twojej stronie; jeśli byłaby asynchroniczna, użytkownik mógłby potencjalnie kliknąć wiele razy i zwrócić wiele obiektów. Synchroniczne wywołanie zapobiegłoby temu i umożliwiłoby utworzenie kolejnego nowego obiektu dopiero po zakończeniu pierwszego, bez względu na to, czy wystąpił błąd, czy nie. Proszę zwrócić uwagę na sformułowania, zrobiłem to transakcja, jak i nie transakcja celowo.
vol7ron

8

Powiedziałbym, że jeśli rozważasz zablokowanie przeglądarki użytkownika, gdy żądanie zostanie zakończone, użyj żądania synchronicznego.

Jeśli celem jest serializacja żądań, można to osiągnąć za pomocą żądań asynchronicznych, uruchamiając wywołanie zwrotne onComplete poprzedniego żądania w następnej kolejności.


1
Hmm, dodałbym do tego przesuwane okno, w przeciwnym razie stracisz w zasadzie czas podróży w obie strony dla każdego żądania
Stephan Eggermont

8

Istnieje wiele rzeczywistych przypadków, w których blokowanie interfejsu użytkownika jest dokładnie pożądanym zachowaniem.

Weź aplikację z wieloma polami, a niektóre pola muszą zostać zweryfikowane przez wywołanie xmlhttp do zdalnego serwera, podając jako dane wejściowe wartość tego pola i inne wartości pól.

W trybie synchronicznym logika jest prosta, blokowanie doświadczane przez użytkownika jest bardzo krótkie i nie ma problemu.

W trybie asynchronicznym użytkownik może zmieniać wartości innych pól podczas walidacji pierwszego. Te zmiany wywołają inne wywołania xmlhttp z wartościami z pola początkowego, które nie zostały jeszcze zweryfikowane. Co się stanie, jeśli wstępna weryfikacja się nie powiedzie? Czysty bałagan. Jeśli tryb synchronizacji stanie się przestarzały i zabroniony, logika aplikacji stanie się koszmarem. Zasadniczo aplikacja musi zostać ponownie napisana, aby zarządzać blokadami (np. Wyłączyć inne elementy podczas procesów walidacji). Złożoność kodu ogromnie wzrasta. Niezastosowanie się do tego może doprowadzić do awarii logiki, a ostatecznie do uszkodzenia danych.

Zasadniczo pytanie brzmi: co jest ważniejsze, niezablokowane doświadczenie interfejsu użytkownika lub ryzyko uszkodzenia danych? Odpowiedź powinna pozostać u programisty aplikacji, a nie do W3C.


1
Myślę, że mylisz pomysł blokowania interakcji użytkownika z blokowaniem wątku przeglądarki. Istnieje miliard prostych sposobów, aby uniemożliwić użytkownikowi kontynuowanie interakcji z jakąkolwiek jednostką (polem formularza itp.) Podczas wywołania asynchronicznego, które nie wymagałyby blokowania wątku przeglądarki. Kiedy wątek się blokuje, nie może być żadnego logicznego przetwarzania, a to jest po prostu zła sytuacja; stwarza znacznie więcej problemów / potencjalnych problemów, które są praktycznie nierozwiązywalne, niż rozwiązuje.
Luke Chavers,

6

Widzę zastosowanie synchronicznych żądań XHR, które mają być używane, gdy zasób w zmiennej lokalizacji musi zostać załadowany przed innymi statycznymi zasobami na stronie, które zależą od pierwszego zasobu, aby w pełni funkcjonować. W rzeczywistości implementuję takie żądanie XHR w małym własnym podprojekcie, podczas gdy zasoby JavaScript znajdują się w różnych lokalizacjach na serwerze w zależności od zestawu określonych parametrów. Kolejne zasoby JavaScript opierają się na tych zasobach zmiennych i takie pliki MUSZĄ zostać załadowane przed załadowaniem innych plików zależnych, dzięki czemu aplikacja jest kompletna.

Ta podstawa pomysłów naprawdę rozszerza się na odpowiedź vol7ron. Procedury oparte na transakcjach to naprawdę jedyny czas, w którym należy wysyłać synchroniczne żądania. W większości innych przypadków wywołania asynchroniczne są lepszą alternatywą, w której po wywołaniu DOM jest aktualizowany w razie potrzeby. W wielu przypadkach, takich jak systemy oparte na użytkownikach, możesz zablokować pewne funkcje dla „nieautoryzowanych użytkowników”, dopóki sami się nie zalogują. Te funkcje, po wywołaniu asynchronicznym, są odblokowywane poprzez procedurę aktualizacji DOM.

Muszę w końcu powiedzieć, że zgadzam się z punktami większości osób w tej sprawie: wszędzie tam, gdzie to możliwe, należy unikać synchronicznych żądań XHR, ponieważ w sposobie działania przeglądarka blokuje się z połączeniami synchronicznymi. Podczas implementacji żądań synchronicznych należy je wykonywać w taki sposób, aby przeglądarka była normalnie zablokowana, na przykład w sekcji NAGŁÓWEK, zanim faktycznie nastąpi załadowanie strony.


Fakt, że działanie opiera się na wyniku innego działania, nie jest powodem do synchronicznego wykonywania tej innej czynności. Tylko wtedy, gdy wynik jakiejś akcji musi zostać przetworzony przed zakończeniem funkcji wywołującej , potrzebne jest wywołanie synchroniczne.
Stijn de Witt

5

Od 2015 roku aplikacje javascript na komputery stacjonarne stają się coraz bardziej popularne. Zwykle w tych aplikacjach podczas ładowania plików lokalnych (i ładowanie ich za pomocą XHR jest całkowicie poprawną opcją), prędkość ładowania jest tak duża, że ​​nie ma sensu nadmiernie komplikować kodu z asynchronizacją. Oczywiście mogą istnieć przypadki, w których asynchronizacja jest drogą do zrobienia (żądanie zawartości z Internetu, ładowanie naprawdę dużych plików lub ogromnej liczby plików w jednej partii), ale poza tym synchronizacja działa dobrze (i jest znacznie łatwiejsza w użyciu) .


W rzeczywistości jest to sytuacja, w której się znajduję i jest rok 2020. Mam aplikację komputerową, która wyświetla swój interfejs przez HTTP, dzięki czemu można uzyskać do niej dostęp z przeglądarki działającej na komputerze lokalnym lub nawet przez sieć. W tych scenariuszach sieć jest szybka i niezawodna, więc wykonywanie synchronicznych żądań XHR jest świetnym sposobem na utrzymanie prostego kodu. Większość ludzi nie zdaje sobie sprawy z tego, że asynchroniczne żądania XHR są jak używanie wątków, a to może być naprawdę skomplikowane z wieloma możliwościami błędów.
Eric Mutta

4

W pewnych okolicznościach jQuery używa wewnętrznie synchronicznego AJAX. Podczas wstawiania kodu HTML zawierającego skrypty przeglądarka ich nie wykona. Skrypty należy uruchamiać ręcznie. Te skrypty mogą dołączać moduły obsługi kliknięć. Załóżmy, że użytkownik klika element przed dołączeniem modułu obsługi, a strona nie będzie działać zgodnie z oczekiwaniami. Dlatego, aby zapobiec sytuacjom wyścigu, do pobierania tych skryptów zostanie użyty synchroniczny AJAX. Ponieważ synchroniczny AJAX skutecznie blokuje wszystko inne, można mieć pewność, że skrypty i zdarzenia będą wykonywane we właściwej kolejności.


3

Powód:

Powiedzmy, że masz aplikację Ajax, która musi wykonać pół tuzina HTTP, aby załadować różne dane z serwera, zanim użytkownik będzie mógł wykonać jakąkolwiek interakcję.

Oczywiście chcesz, aby było to uruchamiane podczas ładowania.

Wywołania synchroniczne działają bardzo dobrze w tym przypadku bez dodatkowej złożoności kodu. To jest proste i nieskomplikowane.

Wada:

Jedyną wadą jest to, że przeglądarka blokuje się do momentu załadowania wszystkich danych lub przekroczenia limitu czasu. Jeśli chodzi o omawianą aplikację Ajax, nie stanowi to większego problemu, ponieważ aplikacja jest bezużyteczna, dopóki wszystkie początkowe dane nie zostaną załadowane.

Alternatywny?

Jednak wiele przeglądarek blokuje wszystkie okna / karty, gdy javascript jest zajęty w którymkolwiek z nich, co jest głupim problemem projektowym przeglądarki - ale w rezultacie blokowanie w możliwie wolnej sieci nie jest grzeczne, jeśli uniemożliwia użytkownikom korzystanie z innych kart podczas oczekiwania na załadowanie strony Ajax.

Wygląda jednak na to, że pobieranie synchroniczne zostało i tak usunięte lub ograniczone w najnowszych przeglądarkach. Nie jestem pewien, czy to dlatego, że ktoś zdecydował, że zawsze byli źli, czy też pisarze przeglądarek byli zdezorientowani przez projekt roboczy WC na ten temat.

http://www.w3.org/TR/2012/WD-XMLHttpRequest-20120117/#the-open-method wygląda na to, że (patrz sekcja 4.7.3) nie możesz ustawić limitu czasu podczas korzystania z trybu blokowania . Wydaje mi się to sprzeczne z intuicją: za każdym razem, gdy blokuje się IO, uprzejmie jest ustawić rozsądny limit czasu, więc po co zezwalać na blokowanie IO, ale nie z limitem czasu określonym przez użytkownika?

Uważam, że blokowanie IO odgrywa kluczową rolę w niektórych sytuacjach, ale musi być poprawnie wdrożone. Chociaż niedopuszczalne jest, aby jedna karta lub okno przeglądarki blokowała wszystkie inne karty lub okna, jest to wada projektowa przeglądarki. Wstyd tam, gdzie należy się wstyd. Ale w niektórych przypadkach jest całkowicie dopuszczalne, aby pojedyncza karta lub okno nie reagowało przez kilka sekund (tj. Przy użyciu blokowania IO / HTTP GET) w niektórych sytuacjach - na przykład podczas ładowania strony, być może dużo danych musi być zanim cokolwiek będzie można zrobić. Czasami prawidłowo zaimplementowany kod blokujący to najczystszy sposób.

Oczywiście równoważną funkcję w tym przypadku można uzyskać za pomocą asynchronicznego pobierania http, ale jaki rodzaj głupiej procedury jest wymagany?

Myślę, że spróbuję czegoś w ten sposób:

Podczas ładowania dokumentu wykonaj następujące czynności: 1: Ustaw 6 globalnych zmiennych flag „Gotowe”, zainicjuj je na 0. 2: Wykonaj wszystkie 6 pobrań w tle (zakładając, że kolejność nie ma znaczenia)

Następnie wywołania zwrotne zakończenia dla każdego z 6 http get ustawiłyby odpowiednie flagi „Gotowe”. Ponadto każde wywołanie zwrotne sprawdzałoby wszystkie inne flagi gotowe, aby zobaczyć, czy wszystkie 6 HTTP zostało zakończone. Ostatnie wywołanie zwrotne do zakończenia, po zobaczeniu, że wszystkie inne zakończyły się, wywoływałby funkcję INIT REAL, która następnie ustawiałaby wszystko, teraz, gdy wszystkie dane zostały pobrane.

Jeśli kolejność pobierania miała znaczenie - lub jeśli serwer sieciowy nie był w stanie zaakceptować wielu żądań w tym samym czasie - potrzebujesz czegoś takiego:

W onload () zostanie uruchomione pierwsze pobieranie http. W jego wywołaniu zwrotnym zostanie uruchomiony drugi. W swoim wywołaniu zwrotnym, trzeci - i tak dalej, i tak dalej, przy czym każde wywołanie zwrotne uruchamia następny HTTP GET. Kiedy ostatni powrócił, wywołałby prawdziwą procedurę init ().


2

Co się stanie, jeśli wykonasz wywołanie synchroniczne w kodzie produkcyjnym?

Niebo spada.

Nie, poważnie, użytkownik nie lubi zablokowanej przeglądarki.


2
Pytanie brzmi: „dlaczego robisz to z XMLHTTPREQUEST” nie „po co synchronizować połączenia”
Itay Moav -Malimovka

1
Jeśli dodasz rozsądny limit czasu, nie powinno to stanowić problemu.
Greg

1
Prosi o przypadki użycia wywołań synchronizacyjnych ... Nie ze względu na ich wady (wszyscy już je znamy ...)
Stijn de Witt

jaki użytkownik? czy wszyscy użytkownicy są tacy sami? co z inżynierami testującymi lokalnie? ... więc dostęp do plików systemu plików z bardzo małym opóźnieniem ????
user2800679

2

Używam go do walidacji nazwy użytkownika, podczas sprawdzania, czy nazwa użytkownika już nie istnieje.

Wiem, że lepiej byłoby zrobić to asynchronicznie, ale wtedy powinienem użyć innego kodu dla tej konkretnej reguły walidacji. Lepiej wyjaśniam. Moja konfiguracja walidacji używa pewnych funkcji walidacji, które zwracają wartość true lub false, w zależności od tego, czy dane są prawidłowe.

Ponieważ funkcja musi powrócić, nie mogę używać technik asynchronicznych, więc po prostu ustawiam tę synchronizację i mam nadzieję, że serwer odpowie na tyle szybko, aby nie było zbyt zauważalne. Gdybym użył wywołania zwrotnego AJAX, musiałbym obsłużyć resztę wykonania inaczej niż inne metody walidacji.


Jedna sztuczka w takim scenariuszu polega na tym, aby pozwolić funkcji walidacji po prostu sprawdzić flagę (która zaczyna się jako false) i po prostu ustawić ją na wartość true lub false, gdy serwer odpowie. po zmianie pola resetujesz flagę i ponownie dzwonisz do serwera.
Stijn de Witt

2

Czasami masz działanie, które zależy od innych. Na przykład akcja B może zostać uruchomiona tylko wtedy, gdy A jest zakończona. Podejście synchroniczne jest zwykle używane w celu uniknięcia warunków wyścigu . Czasami użycie wywołania synchronicznego jest prostszą implementacją niż utworzenie złożonej logiki do sprawdzania każdego stanu wywołań asynchronicznych, które są od siebie zależne.

Problem z tym podejściem polega na tym, że „blokujesz” przeglądarkę użytkownika do czasu zakończenia akcji (do czasu powrotu żądania, zakończenia, załadowania itp.). Dlatego uważaj, używając go.


Pytanie brzmi: „dlaczego robisz to z XMLHTTPREQUEST”, a nie „po co synchronizować połączenia”
Itay Moav -Malimovka

Sam autor mówi: „ Synchroniczne wywołania blokują przeglądarkę, co prowadzi do strasznych wrażeń użytkownika”. w komentarzu, więc wszyscy w tym wątku zastosowali podejście „wywołań synchronicznych”. Dlaczego wziąłeś to dosłowne zrozumienie pytania, skoro nie możesz tak naprawdę powiedzieć na pewno, co autor miał na myśli?
GmonC

2

Używam wywołań synchronicznych podczas tworzenia kodu - cokolwiek zrobiłeś, gdy żądanie było przesyłane do iz serwera, może zaciemnić przyczynę błędu.

Kiedy to działa, robię to asynchronicznie, ale staram się dołączyć licznik przerwania i wywołania zwrotne awarii, ponieważ nigdy nie wiadomo ...


2

SYNC vs ASYNC: Jaka jest różnica?

Zasadniczo sprowadza się to do tego:

console.info('Hello, World!');
doSomething(function handleResult(result) {
    console.info('Got result!');
});
console.info('Goodbye cruel world!');

Kiedy doSomethingjest synchroniczne , wypisze:

Hello, World!
Got result!
Goodbye cruel world!

W przeciwieństwie do tego, jeśli doSomethingjest asynchroniczny , wypisze:

Hello, World!
Goodbye cruel world!
Got result!

Ponieważ funkcja doSomethingwykonuje swoją pracę asynchronicznie, zwraca przed wykonaniem pracy. Wynik uzyskujemy więc dopiero po wydrukowaniuGoodbye cruel world!

Jeśli jesteśmy zależni od wyniku wywołania asynchronicznego, musimy umieścić zależny kod w wywołaniu zwrotnym:

console.info('Hello, World!');
doSomething(function handleResult(result) {
    console.info('Got result!');
    if (result === 'good') {
        console.info('I feel great!');
    }
    else {
        console.info('Goodbye cruel world!');
    }
});

W związku z tym sam fakt, że dwie lub trzy rzeczy muszą się wydarzyć po kolei, nie jest powodem, aby robić je synchronicznie (chociaż kod synchronizacji jest łatwiejszy do pracy dla większości ludzi).

DLACZEGO SYNCHRONICZNY XMLHTTPREQUEST?

Są sytuacje, w których potrzebujesz wyniku przed zakończeniem wywoływanej funkcji. Rozważ ten scenariusz:

function lives(name) {
    return (name !== 'Elvis');
}
console.info('Elvis ' + (lives('Elvis') ? 'lives!' : 'has left the building...');

Załóżmy, że nie mamy kontroli nad kodem wywołującym ( console.infolinią) i musimy zmienić funkcję, livesaby zapytać serwer ... Nie ma sposobu, abyśmy mogli wykonać żądanie asynchroniczne do serwera od wewnątrz livesi nadal mieć odpowiedź przed liveszakończeniem. Więc nie wiedzielibyśmy, czy wrócić, trueczyfalse . Jedynym sposobem uzyskania wyniku przed zakończeniem funkcji jest wykonanie żądania synchronicznego.

Jak Sami Samhuriwspomina w swojej odpowiedzi, bardzo realnym scenariuszem, w którym możesz potrzebować odpowiedzi na żądanie serwera przed zakończeniem funkcji, jest onbeforeunloadzdarzenie, ponieważ jest to ostatnia funkcja z Twojej aplikacji, która kiedykolwiek zostanie uruchomiona przed zamknięciem okna.

NIE POTRZEBUJĘ SYNCHRONIZACJI POŁĄCZEŃ, ALE KORZYSTAM Z NICH JAKIEŚ SĄ ŁATWIEJSZE

Proszę nie. Synchroniczne połączenia blokują przeglądarkę i sprawiają, że aplikacja nie reaguje. Ale masz rację. Kod asynchroniczny jest trudniejszy. Istnieje jednak sposób, aby sobie z tym poradzić. Nie tak proste jak synchronizacja kodu, ale zbliża się: Obietnica s.

Oto przykład: dwa wywołania asynchroniczne powinny zakończyć się pomyślnie, zanim trzeci segment kodu zostanie uruchomiony:

var carRented = rentCar().then(function(car){
  gasStation.refuel(car);
});

var hotelBooked = bookHotel().then(function(reservation) {
  reservation.confirm();
});

Promise.all([carRented, hotelBooked]).then(function(){
  // At this point our car is rented and our hotel booked.
  goOnHoliday();
});

Oto jak byś wdrożył bookHotel:

function bookHotel() {
  return new Promise(function(resolve, reject){
    if (roomsAvailable()) {
      var reservation = reserveRoom();
      resolve(reservation);
    }
    else {
      reject(new Error('Could not book a reservation. No rooms available.'));
    }
  });
}

Zobacz także: Pisz lepiej JavaScript z obietnicami .


1
„Proszę, nie rób tego. Synchroniczne połączenia blokują przeglądarkę i sprawiają, że aplikacja przestaje odpowiadać”. Nie zawsze jest to problem. Wyobraź sobie, że testujesz localhost i jesteś programistą.
user2800679

2

XMLHttpRequestjest tradycyjnie używany do żądań asynchronicznych. Czasami (w przypadku debugowania lub określonej logiki biznesowej) chcesz zmienić wszystkie / kilka wywołań asynchronicznych na jednej stronie w celu synchronizacji.

Chciałbyś to zrobić bez zmiany wszystkiego w kodzie JS. Flaga async / sync daje taką możliwość, a jeśli została zaprojektowana poprawnie, wystarczy zmienić tylko jedną linię w kodzie / zmienić wartość jednej w varczasie wykonywania.



1

Właśnie miałem sytuację, w której asynchroniczne żądania listy adresów URL wywoływanych kolejno za pomocą forEach (i pętli for) powodowałyby anulowanie pozostałych żądań. Przerzuciłem się na synchroniczne i działają zgodnie z przeznaczeniem.


1

Korzystanie z synchronicznych żądań HTTP jest powszechną praktyką w branży reklam mobilnych.

Firmy (zwane też „wydawcami”), które tworzą aplikacje, często wyświetlają reklamy w celu generowania przychodów. W tym celu instalują w swojej aplikacji pakiety SDK reklam. Istnieje wiele (MoPub, Ogury, TapJob, AppNext, Google Ads AdMob).

Te pakiety SDK będą wyświetlać reklamy w widoku internetowym.

Wyświetlając reklamę użytkownikowi, musi to być płynne doświadczenie, zwłaszcza podczas odtwarzania wideo. W żadnym momencie nie powinno być buforowania ani ładowania.

Do rozwiązania tego precachingsłuży. Gdzie media (zdjęcia / filmy / itp.) Są ładowane synchronicznie w tle widoku internetowego.

Dlaczego nie zrobić tego asynchronicznie?

  1. Jest to część ogólnie przyjętego standardu
  2. Pakiet SDK nasłuchuje onloadzdarzenia, aby wiedzieć, kiedy reklama jest „gotowa” do wyświetlenia użytkownikowi

Wraz z wycofaniem synchronicznych żądań XMLHttpRequests firmy reklamowe będą najprawdopodobniej zmuszone do zmiany standardu w przyszłości, chyba że można określić inny sposób.


0

Synchroniczny XHR może być bardzo przydatny do (nieprodukcyjnego) wewnętrznego tworzenia narzędzi i / lub frameworka. Wyobraź sobie na przykład, że chcesz synchronicznie załadować bibliotekę kodu przy pierwszym dostępie, na przykład:

get draw() 
{
    if (!_draw)
    {
       let file;
       switch(config.option)
       {
           case 'svg':
              file = 'svgdraw.js';
              break;
           case 'canvas':
              file = 'canvasdraw.js';
              break;
           default:
              file = 'webgldraw.js';
       }

       var request = new XMLHttpRequest();
       request.open('GET', file, false);
       request.send(null);
       _draw = eval(request.responseText);
    }

    return _draw;
}

Zanim wpadniesz w oszołomienie i ślepo zwymiotujesz zło eval, pamiętaj, że jest to tylko do lokalnych testów. W przypadku kompilacji produkcyjnych _draw byłby już ustawiony.

Twój kod może więc wyglądać następująco:

foo.drawLib.draw.something(); //loaded on demand

To tylko jeden przykład czegoś, co nie byłoby możliwe bez synchronizacji XHR. Możesz załadować tę bibliotekę z góry, tak, lub wykonać obietnicę / wywołanie zwrotne, ale nie możesz załadować biblioteki synchronicznie bez synchronizacji XHR. Pomyśl, jak bardzo tego typu rzeczy mogą oczyścić Twój kod ...

Ograniczenia tego, co możesz z tym zrobić dla narzędzi i struktur (działających lokalnie), są ograniczone tylko przez twoją wyobraźnię. Chociaż wydaje się, że w świecie JavaScript wyobraźnia jest nieco ograniczona.


-1

Oto jeden dobry powód. Chciałem następnie wykonać żądanie http, w zależności od wyniku, wywołać click () na wejściu type = file. Nie jest to możliwe w przypadku asynchronicznego xhr lub pobierania. Wywołanie zwrotne traci kontekst „akcja użytkownika”, więc wywołanie click () jest ignorowane. Synchroniczna xhr uratowała mój boczek.

onclick(event){
    //here I can, but I don't want to.
    //document.getElementById("myFileInput").click();
    fetch("Validate.aspx", { method : "POST", body: formData, credentials: "include" })
    .then((response)=>response.json())
    .then(function (validResult) {
        if (validResult.success) {
            //here, I can't.
            document.getElementById("myFileInput").click();
        }
    });
}

zapisz to na var
Es Noguera
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.