Składnia async/await bazuje na obietnicach. Nie mniej chciałem zapytać czego używacie w swoich projektach zapisu obietnic czy async/await? Jaka składnia jest waszym zdaniem lepsza i dalczego?

- Rejestracja:ponad 9 lat
- Ostatnio:około 3 lata
- Lokalizacja:Warszawa
- Postów:1264
Async/await w wiekszości przypadków, jednak wszystko zależy od tego co chcemy osiągnąć i która wersja będzie czytelniejsza, vide: https://medium.com/@bluepnume/even-with-async-await-you-probably-still-need-promises-9b259854c161

- Rejestracja:prawie 8 lat
- Ostatnio:ponad 6 lat
- Lokalizacja:Warszawa
- Postów:106
Async await jest niby krótszy ale osobiście nie uważam żeby był bardzo logiczny .Zwykłe promisy z metodą then lub catch są bardziej czytelne a async await musisz wsadzić do try catch aby wyłapać ewentualne błędy .

- Rejestracja:ponad 9 lat
- Ostatnio:około 3 lata
- Lokalizacja:Warszawa
- Postów:1264
Async await [...] nie uważam żeby był bardzo logiczny
??
Zwykłe promisy z metodą then lub catch są bardziej czytelne
W prostych przypadkach to kwestia gustu, ale już w choć odrobinę bardziej złożonych przypadkach często async-await jest o wiele czytelniejszy, prosty przykład:
- pobierz wartość
a
, - na podstawie wartości
a
pobierz wartośćb
, - użyj obu wartości w dalszej części kodu
Wersja z .then()
- płaska z dodatkową zmienną:
const example1a = () => {
let a;
return fetchA()
.then(result => {
a = result;
return fetchB(result)
})
.then(b => {
console.log({ a, b })
})
}
Wersja z .then()
z zagnieżdżeniem promisów:
const example1b = () => {
return fetchA()
.then(a => {
return fetchB(a)
.then(b => {
console.log({ a, b })
})
})
}
Wersja z .then()
płaska skrócona (ale z niepotrzebnym pakowaniem w promisa):
const example1b = () => {
return fetchA()
.then(a => Promise.all([a, fetchB(a)]))
.then(([a, b]) => {
console.log({ a, b })
})
}
Wersja async-await:
const example2 = async () => {
const a = await fetchA()
const b = await fetchB(a)
console.log({ a, b })
}
CodePen: https://codepen.io/caderek/pen/MXqMQX?editors=0012
Przykłady można mnożyć (oczywiście, jak wspomniałem w poprzdnim poscie, są tez przykłady drugą stronę, ale imo w praktyce występują zdecydowanie rzadziej).
Podsumowując - moim zdaniem async-await
w nowym kodzie powinien być domyślnym wyborem (o ile oczywiście opieramy się na promisach, bo są przecież inne sposoby), a "low-levelowe" promisy powinny być używane tylko gdy jest to wyraźnie potrzebne (analogicznie do let
vs const
)
- Rejestracja:prawie 9 lat
- Ostatnio:ponad 5 lat
- Lokalizacja:Lublin
- Postów:61
To może podam konkretny przykład, który wyszedł w pracy:
Mamy serwisy w nodejs, które zwracają promise, po kilku transformacjach na innym promise (np. z bazy). Czy lepiej zwracać cały "łańcuch" z then:
return repository.getAll( ... )
...
.then(result => new dto(result));
czy może:
const data = await repository.getAll( ... )
...
return new dto(result)
a może da się to zrobić jeszcze ładniej? (jestem początkujący w node)

- Rejestracja:około 12 lat
- Ostatnio:9 miesięcy
- Postów:53
Moim zdaniem serwis powinien zwracać ostateczny DTO. Za wszelkie transformacje (np. filtrowanie, mapowanie) powinien odpowiadać serwis, a nie warstwa prezentacji. Zatem Twoje drugie podejście jest bardziej logiczne.
Odnośnie:
Zwykłe promisy z metodą then lub catch są bardziej czytelne a async await musisz wsadzić do try catch aby wyłapać ewentualne błędy .
Zasada jest podobna, lecz zamiast then stosujesz await, a catch i tak znajdzie swoje miejsce na samym końcu kodu. Moim zdaniem struktura liniowa pozwala na utrzymanie bardziej przejrzystego kodu, gdyż nie musimy zagłębiać się w argumenty funkcji. Poza tym, kod wykorzystujący async/await można wykorzystać na oba sposoby:
interface IDataDTO {
data1: string;
}
class Service {
private isApiAvailable: boolean = true;
async getData(): Promise<IDataDTO> {
if (!this.isApiAvailable) {
return Promise.reject('Failed');
}
return Promise.resolve<IDataDTO>({
data1: 'Sucess'
});
}
async sendData(data: IDataDTO): Promise<boolean> {
if (!this.isApiAvailable) {
return Promise.reject('Failed');
}
return Promise.resolve(true);
}
}
const exampleAsyncFunction = async () => {
const myService: Service = new Service();
try {
const data = await myService.getData();
const success = await myService.sendData(data);
if (success) {
console.log('Success!');
} else {
console.log('Failed!');
}
} catch(e) {
console.error(e);
}
}
const examplePromiseFunction = () => {
const myService: Service = new Service();
myService.getData()
.then(data => {
return myService.sendData(data);
})
.then(success => {
if (success) {
console.log('Success!');
} else {
console.log('Failed!');
}
})
.catch(e => console.error(e));
}
Zgadzam się z @Maciej Cąderek. W bardziej złożonych przypadkach async/await jest łatwiejsze w utrzymaniu i analizie. Jeżeli zaczynasz przygodę z JS, to async/await powinien być Twoim domyślnym wyborem.