Co to jest Promise?

JavaScript

readTime

6 min

Co to jest Promise?

Jeśli programujesz w JavaScript, na pewno natknąłeś się na pojęcie Promise.

Jest to taki mechanizm, który pomaga zarządzać asynchronicznym kodem, co jest kluczowe w aplikacjach, które muszą działać bez opóźnień, nawet podczas pobierania danych, komunikacji z serwerem, czy wykonywania innych zadań w tle.

W tym artykule dowiesz się, czym jest Promise, jak działa, i jak można go używać do obsługi operacji asynchronicznych.

Oczywiście, wszystko będzie opatrzone przykładami! 😄


Czym jest Promise? 🤔

Promise to obiekt w JavaScript, który obiecuje (stąd nazwa!), że dostarczy wynik pewnej asynchronicznej operacji w przyszłości. Wynik ten może być:

  • Spełniony (fulfilled) – operacja zakończyła się sukcesem i mamy wynik.
  • Odrzucony (rejected) – operacja zakończyła się niepowodzeniem.
  • Oczekujący (pending) – operacja jest w toku i nie mamy jeszcze wyniku.

W praktyce, Promise pozwala nam pisać asynchroniczny kod w bardziej czytelny sposób niż przy użyciu callbacków, co było popularne przed wprowadzeniem Promise w standardzie ES6.


Tworzenie Promise w JavaScript ✨

Aby stworzyć Promise, używamy konstruktora Promise.

Promise przyjmuje funkcję jako argument, która ma dwa parametry: resolve i reject. Resolve to funkcja, która zostanie wywołana, jeśli operacja zakończy się sukcesem, a reject – jeśli zakończy się niepowodzeniem.

Przykład:

javascript
const promise = new Promise((resolve, reject) => {
  let success = true;

  if (success) {
    resolve("Operacja zakończyła się sukcesem!");
  } else {
    reject("Operacja zakończyła się niepowodzeniem.");
  }
});

W powyższym przykładzie tworzymy Promise, który po prostu sprawdza zmienną success.

Jeśli jest prawdą, Promise zostaje spełniony i wywołana zostaje funkcja resolve, w przeciwnym wypadku wywoływana jest funkcja reject.

Asynchroniczność w JavaScript i Promise ⚙️

Promise jest istotnym narzędziem w asynchroniczności w JavaScript.

Operacje takie jak pobieranie danych z serwera, czekanie na odpowiedź z API, czy obsługa czasu z pomocą setTimeout, to operacje asynchroniczne, które często odkładają się na później.

Przykład asynchronicznej operacji:

javascript
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Dane zostały pobrane!");
    }, 2000);
  });
};

fetchData().then((result) => {
  console.log(result); // "Dane zostały pobrane!"
});

Tutaj Promise symuluje operację asynchroniczną przy pomocy setTimeout, a po 2 sekundach zwraca wiadomość, że dane zostały pobrane.


Jak działa Promise? 🔄

Promise działa na zasadzie obietnicy, że pewna operacja zakończy się sukcesem lub niepowodzeniem.

W momencie, gdy operacja jest gotowa, Promise zostaje spełniony albo odrzucony. Wówczas możemy wywołać odpowiednie callbacki, aby obsłużyć wynik.

Metoda .then() – Praca z Promise 💪

Gdy operacja asynchroniczna zakończy się powodzeniem, używamy metody .then(), aby przekazać wynik do dalszego przetwarzania.

Then przyjmuje jako argument funkcję, która zostanie wykonana, gdy Promise zostanie spełniony.

Przykład:

javascript
fetchData().then((result) => {
  console.log(result); // "Dane zostały pobrane!"
});

W tym przypadku, funkcja resolve przekazuje wynik do then, a następnie możemy go wyświetlić lub przetworzyć w inny sposób.


Obsługa błędów – Metoda .catch() 🛑

Nie wszystkie operacje asynchroniczne kończą się sukcesem. W przypadku, gdy Promise zostanie odrzucony, możemy użyć metody .catch(), aby obsłużyć błąd.

Przykład:

javascript
const fetchDataWithError = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("Błąd: nie udało się pobrać danych!");
    }, 2000);
  });
};

fetchDataWithError()
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.error(error); // "Błąd: nie udało się pobrać danych!"
  });

Tutaj symulujemy operację, która kończy się niepowodzeniem, i wywołujemy catch, aby obsłużyć błąd.


Promise Chain – Kolejne operacje 🛠️

Jedną z potężnych cech Promise w JavaScript jest możliwość łańcuchowego wywoływania operacji.

Dzięki temu możemy sekwencyjnie wykonywać kilka operacji asynchronicznych w sposób przejrzysty.

Przykład:

javascript
fetchData()
  .then((result) => {
    console.log(result);
    return fetchData();
  })
  .then((nextResult) => {
    console.log(nextResult);
  })
  .catch((error) => {
    console.error("Wystąpił błąd:", error);
  });

W powyższym przykładzie najpierw wykonujemy jedną operację asynchroniczną, a następnie drugą, gdy pierwsza się zakończy.

Jeśli którakolwiek operacja zakończy się odrzuceniem, wynik zostanie obsłużony w bloku catch.


Promise API i nowoczesne operacje w JavaScript 🚀

Promise API zostało wprowadzone w JavaScript jako część ES6, aby uprościć zarządzanie asynchronicznymi operacjami.

Dodatkowo, dostępne są różne metody, które pomagają w jeszcze łatwiejszym zarządzaniu Promise.


Promise.all() – Równoległe wykonywanie operacji 🚦

Metoda Promise.all() pozwala na wykonanie wielu Promise równolegle i zwrócenie wyników, gdy wszystkie operacje zostaną zakończone.

Jest to przydatne, gdy musimy wykonać wiele asynchronicznych operacji i czekamy na ich wspólny wynik.

Przykład:

javascript
const promise1 = new Promise((resolve) =>
  setTimeout(resolve, 1000, "Promise 1 spełniony")
);
const promise2 = new Promise((resolve) =>
  setTimeout(resolve, 2000, "Promise 2 spełniony")
);

Promise.all([promise1, promise2]).then((results) => {
  console.log(results); // ["Promise 1 spełniony", "Promise 2 spełniony"]
});

Promise.race() – Wyścig pomiędzy Promise ⏱️

Metoda Promise.race() działa podobnie jak Promise.all(), ale zwraca wynik pierwszego Promise, który zostanie spełniony lub odrzucony.

Przykład:

javascript
const promise1 = new Promise((resolve) =>
  setTimeout(resolve, 1000, "Promise 1 spełniony")
);
const promise2 = new Promise((resolve, reject) =>
  setTimeout(reject, 500, "Promise 2 odrzucony")
);

Promise.race([promise1, promise2])
  .then((result) => {
    console.log(result); // "Promise 2 odrzucony"
  })
  .catch((error) => {
    console.error(error);
  });

W tym przypadku Promise.race() zwróci wynik tego Promise, który zakończy się jako pierwszy.


Obsługa błędów w Promise – Zapewnij stabilność aplikacji 💪

W pracy z Promise, szczególnie ważna jest obsługa błędów. Czasem operacje asynchroniczne mogą zakończyć się niepowodzeniem, np. z powodu braku połączenia internetowego lub problemu z serwerem.

Dlatego zawsze warto implementować catch, aby zapewnić odpowiednią obsługę wyjątków.

Przykład:

javascript
fetchData()
  .then((result) => {
    console.log(result);
    return fetchData();
  })
  .catch((error) => {
    console.error("Wystąpił błąd:", error);
  })
  .finally(() => {
    console.log("Operacja zakończona");
  });

Blok finally zostanie wykonany niezależnie od tego, czy Promise zakończył się sukcesem czy niepowodzeniem. To idealne miejsce, aby wykonać czyszczenie zasobów lub wyświetlić komunikat końcowy.


Async/Await – Nowoczesne zarządzanie asynchronicznością 🔥

Promise jest świetny, ale jeszcze bardziej eleganckim sposobem na zarządzanie asynchronicznymi operacjami jest async/await.

Async i await to specjalne słowa kluczowe, które sprawiają, że Promise wyglądają i działają bardziej jak kod synchroniczny, co znacznie ułatwia programowanie. a

Przykład z async/await:

javascript
async function fetchData() {
  try {
    const response = await fetch("https://api.example.com/data");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Błąd podczas pobierania danych:", error);
  }
}

Tutaj nie musisz już używać .then() ani .catch(), ponieważ async/await sprawia, że kod jest bardziej liniowy i intuicyjny.


Podsumowanie: Promise – klucz do asynchroniczności w JavaScript 🔑

Promise to fundament asynchroniczności w JavaScript.

Dzięki nim, możesz obsługiwać operacje takie jak pobieranie danych czy interakcje z API w sposób czytelny i wydajny.

Zrozumienie, jak działa Promise, jak tworzyć je i jak obsługiwać błędy, jest kluczowe, aby tworzyć nowoczesne aplikacje webowe.

Korzystaj z Promise, aby Twoje aplikacje były bardziej responsywne i lepiej zarządzały asynchronicznymi operacjami! 😄

authorImg

Witek Pruchnicki

Z pasją dzielę się wiedzą o programowaniu i nie tylko na różne sposoby