Podręcznik
Asynchroniczność w Node.js
Callbacks
Asynchroniczna funkcja jako jeden z argumentów wejściowych może przyjmować tzw. funkcję callback, która ma zostać wywołana po zakończeniu jej działania. Przykładowo, funkcję readFile z modułu fs można wywołać w następujący sposób:
Funkcja ta wczytuje plik z podanej ścieżki, a następnie wywołuje funkcję [callback]. Nie wiadomo, kiedy ta funkcja zostanie wywołana; wiadomo tylko, że wydarzy się to po wczytaniu pliku. Kod programu, który znajduje się pod wywołaniem readFile, może (choć nie musi) zostać wykonany zanim zostanie wywołana funkcja [callback]. Na przykład:
fs.readFile("my_file.txt", (err, data) => {
if (err) throw err;
console.log("Plik został wczytany");
});
console.log("Funkcja readFile została wywołana")
Plik został wczytany
Piramidy zguby
Problem z używaniem funkcji callback pojawia się, gdy kilka operacji asynchronicznych trzeba wywołać po kolei – np. sięgać kilka razy do bazy danych, za każdym razem korzystając z wyników poprzednich zapytań. Użycie funkcji callback wymaga wówczas zagnieżdżania wielu funkcji, co może pogorszyć czytelność kodu:
operacja1(dane, (wynik1) => {
operacja2(wynik1, (wynik2) => {
operacja3(wynik2, (wynik3) => {
operacja4(wynik3);
});
});
});
}
Kod programu, zawierający liczne zagnieżdżone funkcje callback – jak powyżej – jest trudny w utrzymaniu. Jeśli wystąpi w nim błąd, to trudno jest ten błąd zidentyfikować. Między innymi z tego powodu styl programowania, przedstawiony w powyższym przykładzie, często opatrywany jest nazwami mającymi zniechęcić do jego naśladowania, jak np. callback hell albo pyramid of doom. Używanie promises (opisane w następnym podrozdziale) pozwala na realizację asynchroniczności wolną od tego problemu.
Literatura