Kod asynchroniczny w JavaScript może powodować ból głowy, szczególnie jeśli dopiero zaczynasz z nim pracować. Nowoczesne przeglądarki i środowiska serwerowe, takie jak Node.js, aktywnie wykorzystują asynchroniczność, aby nie blokować wykonania kodu podczas oczekiwania na odpowiedź z serwera, odczyt pliku czy wykonanie zapytania do bazy danych.
Callbacki i ich problemy
Dawniej asynchroniczność w JavaScript była realizowana za pomocą callbacków (funkcji zwrotnych). To są funkcje, które są przekazywane jako argumenty i wywoływane po zakończeniu operacji asynchronicznej.
function fetchData(callback) {
setTimeout(() => {
callback("Dane odebrane!");
}, 1000);
}
fetchData((message) => {
console.log(message);
});
Taki sposób działania działa, ale przy skomplikowaniu logiki może przekształcić się w tzw. “piekło callbacków”:
function step1(callback) {
setTimeout(() => {
console.log("Krok 1");
callback();
}, 1000);
}
function step2(callback) {
setTimeout(() => {
console.log("Krok 2");
callback();
}, 1000);
}
function step3(callback) {
setTimeout(() => {
console.log("Krok 3");
callback();
}, 1000);
}
step1(() => {
step2(() => {
step3(() => {
console.log("Zakończono!");
});
});
});
Taki kod jest trudny do przeczytania, utrzymania i rozwijania. Dlatego wprowadzono Promise.
Promises: nowy poziom asynchroniczności
Obiekt Promise pozwala na pracę z operacjami asynchronicznymi w bardziej zorganizowany sposób.
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Dane odebrane!");
}, 1000);
});
}
fetchData().then((message) => {
console.log(message);
});