promise vs async/await

0

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?

0

Async/await - mogę pisać kod asynchronizczny tak jakby był synchroniczny + normalny try catch

1

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

0

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 .

2

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)

0

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)

0

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.

1 użytkowników online, w tym zalogowanych: 0, gości: 1