Async/await w JavaScript

Async/await w JavaScript

W tym artykule wyjaśnimy async/await w JavaScript.

YouTube Video

Async/await w JavaScript

async (i await) w JavaScript to funkcje zaprojektowane, aby pisanie operacji asynchronicznych było bardziej intuicyjne i czytelne. Korzystając z tego, możesz zmniejszyć złożoność tradycyjnych funkcji zwrotnych i łańcuchów Promise, a kod asynchroniczny pisać w sposób przypominający kod synchroniczny.

Funkcja async

async jest używane do zdefiniowania funkcji jako funkcji asynchronicznej. Funkcja async zawsze zwraca obietnicę (Promise). W funkcji oznaczonej jako async można użyć await, aby poczekać na zwrócenie wyniku obietnicy (Promise).

Podstawowa składnia funkcji async

1async function myAsyncFunction() {
2    // Write asynchronous processing here
3    return 'Result';  // Return a Promise
4}

W tym przypadku wywołanie myAsyncFunction() automatycznie zwraca obiekt Promise. Po rozwiązaniu obietnicy (Promise) jej wynik staje się wartością zwracaną przez return.

Przykład: Podstawowa funkcja async

1async function greet() {
2    return 'Hello, World!';
3}
4
5greet().then((message) => {
6    console.log(message);  // Displays "Hello, World!"
7});

await

await jest używane, aby zaczekać na rozwiązanie obietnicy (Promise). Korzystając z await, możesz wstrzymać wykonywanie kodu, aż obietnica (Promise) zostanie rozwiązana, i odebrać jej wynik. await może być używane tylko wewnątrz funkcji async.

Przykład: Jak używać await

 1async function fetchData() {
 2    // Wait for the result of the Promise
 3    const data = await fetch('https://codesparklab.com/json/example.json');
 4    // Wait for the asynchronous operation to complete
 5    const jsonData = await data.json();
 6    // Retrieve and display the data
 7    console.log(jsonData);
 8}
 9
10fetchData();

W powyższym przykładzie oczekuje na obietnicę (Promise) zwróconą przez funkcję fetch za pomocą await, a następnie wykonuje dalsze operacje asynchroniczne, używając wyniku.

Obsługa błędów z użyciem async/await

Jeśli wewnątrz funkcji async wystąpi błąd, błąd ten jest traktowany jako reject obietnicy (Promise). Możesz użyć instrukcji try...catch, aby obsługiwać błędy.

Przykład: Obsługa błędów

 1async function fetchData() {
 2    try {
 3        // Invalid URL
 4        const data = await fetch('https://invalid.codesparklab.com/');
 5        const jsonData = await data.json();
 6        console.log(jsonData);
 7    } catch (error) {
 8        // Catch the error
 9        console.error('Failed to fetch data:', error);
10    }
11}
12
13fetchData();

Użycie bloku try...catch pozwala wychwytywać błędy występujące podczas operacji asynchronicznych, zapobiegając awarii programu w przypadku wystąpienia błędów.

Zalety async/await

W porównaniu do tradycyjnych łańcuchów Promise, async/await oferuje następujące zalety:.

  • Poprawiona czytelność
    • Przetwarzanie asynchroniczne można pisać jak kod synchroniczny, unikając złożoności głęboko zagnieżdżonych łańcuchów Promise i funkcji zwrotnych.
  • Łatwiejsze debugowanie
    • Ponieważ kod wygląda jak synchroniczny, debugowanie i obsługa błędów są łatwiejsze.
  • Lepsza konserwowalność
    • Procesy asynchroniczne można pisać prościej, co ułatwia wprowadzanie zmian lub modyfikowanie kodu oraz poprawia długoterminową konserwowalność.

Przykład: łańcuch Promise vs async/await

Porównajmy kod wykorzystujący łańcuchy Promise oraz kod z użyciem async/await.

 1// Code using Promise chains
 2function fetchDataPromise() {
 3    fetch('https://codesparklab.com/json/example.json')
 4        .then((response) => response.json())
 5        .then((data) => {
 6            console.log(data);
 7        })
 8    .catch((error) => {
 9        console.error('Failed to fetch data:', error);
10    });
11}
12
13// Code using async/await
14async function fetchDataAsync() {
15    try {
16        const response = await fetch('https://codesparklab.com/json/example.json');
17        const data = await response.json();
18        console.log(data);
19    } catch (error) {
20        console.error('Failed to fetch data:', error);
21    }
22}

Jak widać, użycie async/await pozwala pisać procesy asynchroniczne w sposób liniowy, co skutkuje bardziej czytelnym kodem.

Wykonywanie wielu operacji asynchronicznych jednocześnie

Łącząc Promise.all() lub Promise.race() z await, możesz wykonywać wiele operacji asynchronicznych jednocześnie i zbiorczo obsługiwać ich wyniki.

Promise.all()

 1async function fetchMultipleData() {
 2    try {
 3        const [data1, data2] = await Promise.all([
 4            fetch('https://codesparklab.com/json/example1.json'),
 5            fetch('https://codesparklab.com/json/example2.json')
 6        ]);
 7        const jsonData1 = await data1.json();
 8        const jsonData2 = await data2.json();
 9        console.log(jsonData1);
10        console.log(jsonData2);
11    } catch (error) {
12        console.error('Failed to fetch data:', error);
13    }
14}
15
16fetchMultipleData();
  • Promise.all() rozwiązuje wiele obietnic (Promise) jednocześnie i zwraca ich wyniki w postaci tablicy. Czeka, aż wszystkie obietnice (Promise) zostaną rozwiązane, a jeśli którakolwiek z nich się nie powiedzie, cały proces jest uznawany za niepowodzenie.

Promise.race()

 1async function fetchFastestData() {
 2    try {
 3        const fastestResponse = await Promise.race([
 4            fetch('https://codesparklab.com/json/example1.json'),
 5            fetch('https://codesparklab.com/json/example2.json')
 6        ]);
 7        const jsonData = await fastestResponse.json();
 8        console.log('Fastest data:', jsonData);
 9    } catch (error) {
10        console.error('Fetch error:', error);
11    }
12}
13
14fetchFastestData();
  • Promise.race() zwraca wynik pierwszej obietnicy (Promise), która zostanie spełniona lub odrzucona. Jest to przydatne, gdy chcesz zareagować na tę operację asynchroniczną, która zakończy się jako pierwsza. Jednak jeśli pierwsza obietnica (Promise) zakończy się niepowodzeniem, błąd zostanie natychmiast przechwycony przez catch.

Promise.allSettled()

 1async function fetchWithAllSettled() {
 2    const results = await Promise.allSettled([
 3        // This URL will success
 4        fetch('https://codesparklab.com/json/example1.json'),
 5        // This URL will fail
 6        fetch('https://invalid.codesparklab.com/')
 7    ]);
 8
 9    results.forEach((result, index) => {
10        if (result.status === 'fulfilled') {
11            const url = result.value.url;
12            console.log(`Request ${index + 1} succeeded:`, url);
13        } else {
14            const reason = result.reason;
15            console.warn(`Request ${index + 1} failed:`, reason);
16        }
17    });
18}
19
20fetchWithAllSettled();
  • Promise.allSettled() czeka na wszystkie wyniki, niezależnie od tego, czy zakończyły się powodzeniem, czy niepowodzeniem. Każdy wynik jest zwracany w postaci { status, value } lub { status, reason }, co pozwala określić, które obietnice (Promise) zakończyły się powodzeniem, a które niepowodzeniem.

Promise.any()

 1async function fetchAnySuccessful() {
 2    try {
 3        const firstSuccessful = await Promise.any([
 4            // This URL will fail
 5            fetch('https://invalid.codesparklab.com/'),
 6            // This URL will success
 7            fetch('https://codesparklab.com/json/example1.json')
 8        ]);
 9        const jsonData = await firstSuccessful.json();
10        console.log('First successful response:', jsonData);
11    } catch (error) {
12        console.error('All fetch requests failed:', error);
13    }
14}
15
16fetchAnySuccessful();
  • Promise.any() zwraca tylko wynik pierwszej pomyślnie spełnionej obietnicy (Promise). Wyjątek jest zgłaszany tylko wtedy, gdy wszystkie obietnice (Promise) zakończą się niepowodzeniem. Można tego użyć jako mechanizmu ponawiania prób w środowiskach, gdzie niektóre API są zawodne, dopóki jedna z nich się nie powiedzie.

Podsumowanie

  • Funkcja async: Zawsze zwraca Promise i jest używana do pisania przetwarzania asynchronicznego.
  • await: Używane do oczekiwania na rozwiązanie Promise i pobranie jego wyniku.
  • Obsługa błędów: Używaj try...catch do obsługi błędów, które występują podczas przetwarzania asynchronicznego.
  • Wiele operacji asynchronicznych: Używając metod takich jak Promise.all(), możesz wykonywać wiele zadań asynchronicznych jednocześnie.

async/await to potężne narzędzia do obsługi przetwarzania asynchronicznego, dlatego warto z nich korzystać, aby uprościć złożoną logikę asynchroniczną.

Możesz śledzić ten artykuł, korzystając z Visual Studio Code na naszym kanale YouTube. Proszę również sprawdzić nasz kanał YouTube.

YouTube Video