Async / await

Async/await to nowy sposób na zapis asynchronicznego kodu. Dzięki tym słowom praca z obietnicami zaczyna przypominać synchroniczny kod.

Async

Słowo async postawione przed dowolną funkcją tworzy z niej funkcję asynchroniczną, która zwraca obietnicę. Dzięki temu możemy później na nią reagować poznanymi w poprzednim rozdziale funkcjami:

function doThings() {
    return Promise.resolve("ok");
}

doThings()
    .then(res => {
        console.log(res);
    })


//to samo co
async function doThings() {
    return "ok";
}

doThings()
    .then(res => {
        console.log(res); //"ok"
    });

Await

Słowo kluczowe await sprawia, że JavaScript poczeka na wykonanie asynchronicznego kodu. Dzięki temu zapis bardzo przypomina synchroniczny kod:

Słowa await możemy używać tylko wewnątrz funkcji poprzedzonej słowem async:

Niektórzy programiści wiedząc, że będą używać sporo asynchronicznych operacji wewnątrz swojego kodu, cały kod okrywają IIFE z async lub zdarzeniem DOMContentLoaded:

Przy czym w ES2022 zostanie to zmienione tak, byśmy mogli używać async w głównym kodzie - nawet poza funkcjami (pkt 3).

Obsługa błędów

W przypadku obsługi błędów za pomocą async/await, możemy posłużyć się konstrukcją try/catch, wewnątrz której spróbujemy wykonać jakieś operacje. Jeżeli one się nie powiodą przejmiemy komunikat błędu w sekcji catch:

Możemy też mieszać składnię async/await z then/catch:

Równoczesne operacje

Instrukcja await oznacza to, że kolejna operacja rozpocznie się dopiero, gdy poprzednia się zakończy.

W wielu momentach bardziej optymalnie będzie, gdy nasze operacje wywołamy równocześnie i poczekamy na ich zakończenie:

W przypadku zapisu za pomocą Promise kod mógłby wyglądać tak:

Mały przykład

Bardzo często omawiając asynchroniczność, pierwsze co nam przychodzi do głowy to pobieranie czy wysyłanie danych. Ale przecież operacje zajmujące jakiś czas wcale nie muszą wiązać się z przesyłaniem danych.

Podsumujmy ten rozdział mini przykładem. Mamy klasę, która tworzy i za pomocą setInterval animuje wykres:

Na jej bazie tworzymy pięć wykresów w jakimś testowym elemencie:

Po odpaleniu powyższego kodu dostaniemy 5 wykresów, które równocześnie zaczną się zapełniać.

Chcielibyśmy, by kolejne wykresy zaczęły się zapełniać jeden po drugim.

Funkcja animująca trwa jakiś czas, więc musimy jakoś zareagować na jej zakończenie.

Moglibyśmy więc jak w poprzednim rozdziale zrobić to za pomocą funkcji zwrotnej:

Wtedy reagowanie na zakończenie animacji zmusiło by nas do zagnieżdżania kolejnych wywołań.

Możemy więc pokusić się o zamianę funkcji animate() na obietnicę, dzięki czemu jej późniejsze użycie się uprości:

Ale możemy też połączyć to ze składnią async/await, co jeszcze bardziej uprości nasz kod:

Last updated