Po pierwsze, jest to bardzo szczególny przypadek, gdy celowo zrobimy to w niewłaściwy sposób, aby zmodernizować asynchroniczne wywołanie w bardzo synchroniczną bazę kodu, która ma wiele tysięcy linii, a czas nie pozwala obecnie na wprowadzenie zmian w „zrobić dobrze ”. Boli mnie każde włókno mojej istoty, ale rzeczywistość i ideały często się nie łączą. Wiem, że to do bani.
OK, to na marginesie, jak to zrobić, żebym mógł:
function doSomething() {
var data;
function callBack(d) {
data = d;
}
myAsynchronousCall(param1, callBack);
// block here and return data when the callback is finished
return data;
}
Wszystkie przykłady (lub ich brak) wykorzystują biblioteki i / lub kompilatory, które nie są wykonalne dla tego rozwiązania. Potrzebuję konkretnego przykładu, jak to zablokować (np. NIE zostawiaj funkcji doSomething, dopóki nie zostanie wywołane wywołanie zwrotne) BEZ zamrażania interfejsu użytkownika. Jeśli coś takiego jest możliwe w JS.
źródło
Odpowiedzi:
DOBRZE. ale naprawdę powinieneś to zrobić we właściwy sposób ... czy cokolwiek
Nie, nie można zablokować działającego JavaScript bez blokowania interfejsu użytkownika.
Biorąc pod uwagę brak informacji, trudno jest zaproponować rozwiązanie, ale jedną z opcji może być włączenie funkcji wywoływania w celu sprawdzenia zmiennej globalnej, a następnie ustawienia wywołania zwrotnego
data
na wartość globalną.Wszystko to zakłada, że możesz modyfikować
doSomething()
. Nie wiem czy to jest w kartach.Jeśli można to zmodyfikować, to nie wiem, dlaczego po prostu nie oddzwonisz,
doSomething()
aby zostać wywołanym z innego oddzwaniania, ale lepiej przestanę, zanim wpadnę w kłopoty. ;)Co do cholery. Podałeś przykład, który sugeruje, że można to zrobić poprawnie, więc pokażę to rozwiązanie ...
Ponieważ twój przykład zawiera wywołanie zwrotne, które jest przekazywane do wywołania asynchronicznego, właściwym sposobem byłoby przekazanie funkcji do
doSomething()
wywołania z wywołania zwrotnego.Oczywiście, jeśli to jedyna czynność wywołania zwrotnego, wystarczy przekazać
func
bezpośrednio ...źródło
callback
funkcję domyAsynchronousCall
funkcji, która wykonuje swoje asynchroniczne czynności i wywołuje wywołanie zwrotne po zakończeniu. Oto demo.Funkcje asynchroniczne , funkcja w ES2017 , sprawiają, że kod asynchroniczny wygląda na zsynchronizowany przy użyciu obietnic (szczególnej formy kodu asynchronicznego) i
await
słowa kluczowego. Zwróć też uwagę na przykłady kodu poniżej słowa kluczowegoasync
przedfunction
słowem kluczowym, które oznacza funkcję asynchroniczną / oczekującą. Słowoawait
kluczowe nie będzie działać bez funkcji wstępnie ustawionej za pomocąasync
słowa kluczowego. Ponieważ obecnie nie ma wyjątku od tego, co oznacza, że nie będzie oczekiwał żaden poziom najwyższy (poziom najwyższy czeka, co oznacza oczekiwanie poza jakąkolwiek funkcją). Chociaż jest propozycja na najwyższym poziomieawait
.ES2017 został ratyfikowany (tj. Sfinalizowany) jako standard dla JavaScript w dniu 27 czerwca 2017 r. Async oczekuje może już działać w przeglądarce, ale jeśli nie, nadal możesz korzystać z tej funkcji za pomocą transpilatora javascript, takiego jak babel lub traceur . Chrome 55 ma pełne wsparcie funkcji asynchronicznych. Jeśli masz nowszą przeglądarkę, możesz wypróbować poniższy kod.
Zobacz tabelę zgodności kangax es2017 dla kompatybilności przeglądarki.
Oto przykładowa wywoływana funkcja asynchroniczna,
doAsync
która wymaga trzech jednosekundowych pauz i drukuje różnicę czasu po każdej pauzie od czasu rozpoczęcia:Po umieszczeniu słowa kluczowego oczekującego przed wartością przyrzeczenia (w tym przypadku wartością przyrzeczenia jest wartość zwrócona przez funkcję doSomethingAsync) słowo kluczowe oczekujące wstrzyma wykonanie wywołania funkcji, ale nie wstrzyma żadnych innych funkcji i będzie kontynuowane wykonywanie innego kodu, dopóki obietnica nie zostanie rozwiązana. Po spełnieniu obietnicy odwija wartość obietnicy i możesz pomyśleć o wyrażeniu oczekiwania i obietnicy, które jest teraz zastępowane przez tę nieopakowaną wartość.
Tak więc, ponieważ czekanie tylko pauza czeka, a następnie rozpakowuje wartość przed wykonaniem reszty linii, możesz użyć jej do pętli i wywołań funkcji wewnętrznych, jak w poniższym przykładzie, który zbiera oczekiwane różnice czasowe w tablicy i drukuje tablicę.
Sama funkcja asynchroniczna zwraca obietnicę, dzięki czemu można jej użyć jako obietnicy z łańcuchem takim jak ja powyżej lub w innej funkcji oczekującej asynchronizacji.
Funkcja powyżej czekałaby na każdą odpowiedź przed wysłaniem kolejnego żądania, jeśli chcesz wysłać żądania jednocześnie, możesz użyć Promise.all .
Jeśli obietnica prawdopodobnie zostanie odrzucona, możesz zawinąć ją w try catch lub pomiń try catch i pozwolić, aby błąd rozprzestrzenił się na wywołanie funkcji async / oczekuj. Należy uważać, aby nie pozostawić nieobsługiwanych błędów obietnicy, szczególnie w Node.js. Poniżej kilka przykładów, które pokazują, jak działają błędy.
Jeśli pójdziesz tutaj , możesz zobaczyć gotowe propozycje przyszłych wersji ECMAScript.
Alternatywą dla tego, która może być używana tylko z ES2015 (ES6), jest użycie specjalnej funkcji, która otacza funkcję generatora. Funkcje generatora mają słowo kluczowe wydajności, które może być użyte do replikacji słowa kluczowego oczekującego z funkcją otaczającą. Słowo kluczowe wydajności i funkcja generatora są znacznie bardziej ogólne i mogą robić znacznie więcej niż tylko to, co robi funkcja asynchroniczna. Jeśli chcesz otoki funkcji generatora, której można użyć do replikacji asynchronizacji, czekam co.js . Nawiasem mówiąc, funkcja co podobnie jak async oczekuje na funkcje zwracające obietnicę. Szczerze mówiąc, w tym momencie kompatybilność przeglądarki jest prawie taka sama zarówno dla funkcji generatora, jak i funkcji asynchronicznych, więc jeśli chcesz, aby funkcja async oczekiwała funkcjonalności, powinieneś używać funkcji asynchronicznych bez co.js.
Obsługa przeglądarek jest teraz całkiem dobra dla funkcji Async (od 2017 r.) We wszystkich głównych przeglądarkach (Chrome, Safari i Edge) z wyjątkiem IE.
źródło
Spójrz na obietnice JQuery:
http://api.jquery.com/promise/
http://api.jquery.com/jQuery.when/
http://api.jquery.com/deferred.promise/
Zmień kod:
źródło
dfd.notify(data)
dodfd.resolve(data)
Jest jedno miłe obejście na http://taskjs.org/
Korzysta z generatorów, które są nowością w javascript. Dlatego obecnie nie jest implementowany przez większość przeglądarek. Przetestowałem to w firefoxie i dla mnie to dobry sposób na zawinięcie funkcji asynchronicznej.
Oto przykładowy kod z projektu GitHub
źródło
Państwo może zmusić asynchroniczny JavaScript w NodeJS być synchroniczny z synchronizacją-RPC .
Zdecydowanie jednak zamrozi twój interfejs użytkownika, więc wciąż jestem niezdecydowany, jeśli chodzi o to, czy można skorzystać ze skrótu, którego potrzebujesz. Nie można zawiesić jedynego wątku w JavaScript, nawet jeśli NodeJS pozwala czasem go zablokować. Żadne wywołania zwrotne, zdarzenia, wszystko asynchroniczne w ogóle nie będzie w stanie przetworzyć, dopóki obietnica się nie spełni. Tak więc, chyba że czytelnik ma nieuniknioną sytuację, taką jak OP (lub, w moim przypadku, pisze chwalebny skrypt powłoki bez wywołań zwrotnych, zdarzeń itp.), NIE Rób tego!
Ale oto jak możesz to zrobić:
./calling-file.js
./my-asynchronous-call.js
OGRANICZENIA:
Oba są konsekwencją sposobu
sync-rpc
implementacji, który polega na nadużyciachrequire('child_process').spawnSync
:JSON.stringify
będą wchodzić i wychodzić , więc funkcje i właściwości niepoliczalne, takie jak łańcuchy prototypów, zostaną utracone.źródło
Możesz także przekształcić go w wywołania zwrotne.
źródło
To, czego chcesz, jest teraz możliwe. Jeśli możesz uruchomić kod asynchroniczny w pracowniku usługowym, a kod synchroniczny w pracowniku internetowym, możesz poprosić pracownika sieci web o wysłanie synchronicznego XHR do pracownika usługowego, a gdy pracownik usługowy wykonuje czynności asynchroniczne, pracownik sieciowy wątek będzie czekać. To nie jest świetne podejście, ale może zadziałać.
źródło
Pomysł, który masz nadzieję osiągnąć, można zrealizować, jeśli nieco poprawisz wymagania
Poniższy kod jest możliwy, jeśli środowisko wykonawcze obsługuje specyfikację ES6.
Więcej informacji o funkcjach asynchronicznych
źródło
SyntaxError: await is only valid in async functions and async generators
. Nie wspominając o tym, że param1 nie jest zdefiniowany (i nawet nie używany).