Czy asynchronizacja w przeglądarce jest naprawdę nieblokująca?
Bawiłem się tą funkcją w SPA używając maszynopisu i natywnych obietnic i zauważyłem, że nawet jeśli zmienię długo działającą funkcję w funkcję asynchroniczną zwracającą obietnicę, interfejs nadal nie odpowiada.
Więc moje pytania to:
W jaki sposób nowa funkcja async / wait pomaga uniknąć blokowania interfejsu użytkownika w przeglądarce? Czy są jakieś specjalne dodatkowe kroki, które należy podjąć podczas korzystania z asynchronicznego / oczekującego, aby rzeczywiście uzyskać responsywny UI?
Czy ktoś może stworzyć fiddle, aby zademonstrować jak async / wait pomaga uczynić interfejs responsywnym?
Jak async / wait ma się do wcześniejszych funkcji async, takich jak setTimeout i XmlHttpRequest?
3 answers
await p
planuje wykonanie reszty funkcji po rozwiązaniu promise p
. To wszystko.
async
pozwala na użycie await
. To (prawie) wszystko, co robi (to również owija Twój wynik w obietnicę).
Razem sprawiają, że kod nieblokujący czyta się jak prostszy kod blokujący. Nie odblokowują kodu.
Aby uzyskać responsywny interfejs użytkownika, odciążaj pracę CPU do wątku worker i przesyłaj do niego wiadomości:async function brutePrime(n) {
function work({data}) {
while (true) {
let d = 2;
for (; d < data; d++) {
if (data % d == 0) break;
}
if (d == data) return self.postMessage(data);
data++;
}
}
let b = new Blob(["onmessage =" + work.toString()], {type: "text/javascript"});
let worker = new Worker(URL.createObjectURL(b));
worker.postMessage(n);
return await new Promise(resolve => worker.onmessage = e => resolve(e.data));
}
(async () => {
let n = 700000000;
for (let i = 0; i < 10; i++) {
console.log(n = await brutePrime(n + 1));
}
})().catch(e => console.log(e));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-17 01:38:49
async
jest bardziej eleganckim sposobem na strukturę kodu asynchronicznego. Nie pozwala na żadne nowe możliwości; to po prostu lepsza składnia niż wywołania zwrotne lub obietnice.
Więc async
nie można użyć do "stworzenia czegoś asynchronicznego". Jeśli masz kod, który musi wykonywać wiele procesów opartych na CPU, async
nie będzie magicznie reagować interfejs użytkownika. To, co musisz zrobić, to użyć czegoś w rodzaju web workers , które są właściwym narzędziem do pchania pracy związanej z CPU do wątku w tle w aby interfejs był responsywny.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-14 02:03:11
JavaScript jest jednowątkowy i działa w tym samym wątku co interfejs użytkownika. Więc cały kod JavaScript zablokuje interfejs użytkownika. Jak wspomniano przez innych pracowników sieci mogą być używane do uruchamiania kodu w innych wątkach, ale mają ograniczenia.
Różnica między funkcjami asynchronicznymi a regularnymi polega na tym, że zwracają one obietnicę. Za pomocą wywołania zwrotnego można następnie odroczyć wykonanie kodu, który obsługuje wynik wywołania funkcji, a tym samym pozwala UI wykonać pewną pracę. Następujące trzy przykłady mają ten sam efekt:
async function foo() {
console.log("hi");
return 1;
}
foo().then(result => console.log(result))
console.log("lo");
function foo() {
console.log("hi");
return 1;
}
Promise.resolve(foo()).then(result => console.log(result))
console.log("lo");
function foo() {
console.log("hi");
return 1;
}
const result = foo();
setTimeout(() => console.log(result));
console.log("lo");
We wszystkich trzech przypadkach konsola rejestruje hi, lo, 1. Przed wydrukowaniem 1 interfejs użytkownika może obsługiwać wprowadzanie danych przez użytkownika lub rysowanie aktualizacji. Powodem 1, który jest drukowany jako ostatni w dwóch pierwszych przypadkach, jest to, że wywołania zwrotne dla obietnic nie są wykonywane natychmiast.
await
pozwala to zrobić bez wywołania zwrotnego:
async function foo() {
console.log("hi");
return 1;
}
async function bar() {
const result = await foo();
console.log(result);
}
bar();
console.log("lo");
To również wydrukuje hi, lo, 1. Podobnie jak wywołanie zwrotne dla obietnicy, kod po await
nigdy nie jest wykonywany od razu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-16 12:11:48