3.1 Tworzenie grup promesów
Grupy promesów pozwalają na sekwencyjne wykonywanie kilku operacji asynchronicznych, przekazując wynik jednej operacji do następnej. To sprawia, że kod staje się bardziej czytelny i łatwiejszy do zarządzania. Dodatkowo, promesy oferują potężne możliwości do obsługi błędów, pozwalając tworzyć niezawodne i odporne na awarie aplikacje.
Podstawowa koncepcja
Grupa promesów jest tworzona poprzez zwrócenie nowej promesy z metody then. Każda metoda then zwraca nową promesę, co pozwala zbudować sekwencyjne operacje asynchroniczne.
Przykład prostej grupy promesów
W tym przykładzie każda metoda then wykonuje swoją operację i przekazuje wynik do następnej metody then.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Step 1 completed');
}, 1000);
});
promise
.then((result) => {
console.log(result); // Wyświetli: Step 1 completed
return 'Step 2 completed';
})
.then((result) => {
console.log(result); // Wyświetli: Step 2 completed
return 'Step 3 completed';
})
.then((result) => {
console.log(result); // Wyświetli: Step 3 completed
})
.catch((error) => {
console.error(error);
});
Przykład grupy z operacjami asynchronicznymi
W tym przykładzie każda metoda then czeka na zakończenie operacji asynchronicznej przed wykonaniem kolejnego kroku:
function asyncOperation(step) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`${step} completed`);
}, 1000);
});
}
asyncOperation('Step 1')
.then((result) => {
console.log(result); // Wyświetli: Step 1 completed
return asyncOperation('Step 2');
})
.then((result) => {
console.log(result); // Wyświetli: Step 2 completed
return asyncOperation('Step 3');
})
.then((result) => {
console.log(result); // Wyświetli: Step 3 completed
})
.catch((error) => {
console.error(error);
});
3.2 Obsługa błędów w grupach promesów
Metoda catch jest używana do obsługi błędów w grupie promesów. Jeśli w którejkolwiek z promesów wystąpi błąd, zostanie on przekazany do najbliższej metody catch. To pozwala na centralizowaną obsługę błędów, poprawiając czytelność i utrzymanie kodu.
Przykład obsługi błędów
W tym przykładzie błąd, który wystąpił w Step 2, jest przechwytywany przez metodę catch, a kolejne metody then nie są wykonywane:
function asyncOperation(step, shouldFail = false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) {
reject(`${step} failed`);
} else {
resolve(`${step} completed`);
}
}, 1000);
});
}
asyncOperation('Step 1')
.then((result) => {
console.log(result);
return asyncOperation('Step 2', true); // Ta operacja zakończy się błędem
})
.then((result) => {
console.log(result); // Ten kod nie zostanie wykonany
return asyncOperation('Step 3');
})
.then((result) => {
console.log(result); // Ten kod nie zostanie wykonany
})
.catch((error) => {
console.error('Error:', error); // Wyświetli: Error: Step 2 failed
});
Obsługa błędów w konkretnych krokach
Czasami wymagane jest obsługiwanie błędów w konkretnych krokach grupy, nie przerywając wykonania całej grupy. Do tego można użyć zagnieżdżonych metod then i catch.
Przykład obsługi błędów w konkretnych krokach
W tym przykładzie błąd w Step 2 jest obsługiwany lokalnie, a grupa kontynuuje wykonywanie z odzyskaną wartością:
function asyncOperation(step, shouldFail = false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) {
reject(`${step} failed`);
} else {
resolve(`${step} completed`);
}
}, 1000);
});
}
asyncOperation('Step 1')
.then((result) => {
console.log(result);
return asyncOperation('Step 2', true).catch((error) => {
console.warn('Handled error in Step 2:', error);
return 'Recovered from Step 2 error';
});
})
.then((result) => {
console.log(result); // Wyświetli: Recovered from Step 2 error
return asyncOperation('Step 3');
})
.then((result) => {
console.log(result); // Wyświetli: Step 3 completed
})
.catch((error) => {
console.error('Error:', error); // Ten kod nie zostanie wykonany
});
3.3 Użycie finally
Metoda finally jest używana do wykonania kodu niezależnie od tego, czy promesa zakończyła się sukcesem, czy błędem. Jest to przydatne do wykonywania końcowych działań, takich jak zwolnienie zasobów.
Przykład użycia finally:
function asyncOperation(step, shouldFail = false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) {
reject(`${step} failed`);
} else {
resolve(`${step} completed`);
}
}, 1000);
});
}
asyncOperation('Step 1')
.then((result) => {
console.log(result);
return asyncOperation('Step 2');
})
.then((result) => {
console.log(result);
return asyncOperation('Step 3');
})
.catch((error) => {
console.error('Error:', error);
})
.finally(() => {
console.log('All operations completed'); // Będzie wykonane w każdym przypadku
});
W tym przykładzie metoda finally jest wykonywana w każdym przypadku, niezależnie od tego, czy wystąpił błąd, czy nie.
GO TO FULL VERSION