programing

비동기/대기와 함께 관찰 가능을 사용하는 것이 좋은 방법입니까?

iphone6s 2023. 7. 26. 21:40
반응형

비동기/대기와 함께 관찰 가능을 사용하는 것이 좋은 방법입니까?

나는 관찰 가능한 것을 반환하는 각진 2 공통 http를 사용하고 있지만 중첩된 관찰 가능한 호출을 사용할 때 내 코드가 메시를 좋아한다는 문제에 직면했습니다.

this.serviceA.get().subscribe((res1: any) => {
   this.serviceB.get(res1).subscribe((res2: any) => {
       this.serviceC.get(res2).subscribe((res3: any) => {

       })
   })
})

이제 비동기/대기를 사용하여 이를 방지하고 싶지만 비동기/대기는 Promise에서만 작동합니다.Observable이 Promise로 변환될 수 있다는 것은 알고 있지만, 제가 알고 있는 바와 같이 좋은 방법은 아닙니다.그럼 제가 여기서 무엇을 해야 하나요?

그나저나 비동기/wait :D로 해결할 수 있는 예제 코드를 누군가 나에게 줄 수 있다면 좋을 것 같습니다.

코드에서 수행하려는 순서대로 관찰 가능한 항목을 연결합니다.

코드 예제와 관련하여 관찰 가능한 항목을 연결하려면 다음을 사용합니다(이전 배출 후에 다른 항목을 트리거).flatMap(또는)switchMap목적을 :) 이적목:

this.serviceA.get()
  .flatMap((res1: any) => this.serviceB.get())
  .flatMap((res2: any) => this.serviceC.get())
  .subscribe( (res3: any) => { 
    .... 
  });

이것은 둥지를 만드는 것보다 더 나은 연습입니다. 왜냐하면 이것은 상황을 더 명확하게 만들고 처음에 관찰 가능한 것과 약속이 예방하는 데 도움을 주기로 했던 지옥의 지옥의 콜백을 피하는 데 도움이 될 것이기 때문입니다.

또한사고려다니합을용다를 사용하는 .switchMapflatMap기본적으로 첫 번째 요청이 새 값을 방출하는 경우 다른 요청을 '제거'할 수 있습니다.예를 들어 나머지를 트리거하는 첫 번째 관찰 가능 항목이 버튼의 일부 클릭 이벤트인 경우 사용하기 좋습니다.

다양한 서로차로기다는다요필청않요다수있사습니경용할우은지하례리이양한▁if다▁▁use▁to▁▁can수▁you▁various서▁in로,▁other사▁don를 사용할 수 있습니다.forkJoin또는zip이 모든 것을 한 번에 시작하려면 @Dan Macak 답변을 참조하십시오. 자세한 내용과 기타 통찰력은 다음과 같습니다.


각진 '비동기식' 파이프와 관찰 가능한 부품이 서로 잘 작동합니다.

각도는 할 수 .| async코드에서 하여 이 가능한 항목에서 .


ES6 비동기식 / 관찰 가능한 것 대신 대기 및 약속?

관찰할 수 있는 기능을 직접 사용하지 않으려는 경우 사용할 수 있습니다..toPromise()몇 가지 비동기/대기 명령을 사용할 수 있습니다.

기본 API 호출의 경우와 마찬가지로 관찰 가능한 결과 하나만 반환해야 하는 경우 관찰 가능한 결과는 약속과 상당히 동등한 것으로 볼 수 있습니다.

하지만 이미 Observable이 제공하는 모든 것을 고려할 때, 그렇게 할 필요가 있는지 확신할 수 없습니다. (독자들에게: 계몽적인 반례는 환영합니다!). 저는 가능할 때마다 훈련 연습으로 Observable을 사용하는 것에 더 찬성합니다.


이에 대한 몇 가지 흥미로운 블로그 기사(그리고 다른 기사들도 많이 있습니다):

https://medium.com/ @benlesh/benjs-disc-disc-disc-disc-disc-disc-beb05306875.

ToPromise 함수는 실제로 "연산자"가 아니라 RxJS 전용 수단으로 관찰 가능한 것을 구독하고 약속으로 포장하기 때문에 실제로 약간 까다롭습니다.약속은 관찰이 완료되면 관찰 가능한 마지막으로 방출된 값으로 해결됩니다.즉, 관찰 가능한 값 "hi"를 내보낸 후 완료될 때까지 10초 동안 기다리면 반환된 약속이 "hi"를 해결하기 전에 10초 동안 기다립니다.관찰 가능 항목이 완료되지 않으면 약속이 해결되지 않습니다.

참고: 비동기 대기와 같이 Promise를 기대하는 API를 다루는 경우를 제외하고 to Promise()를 사용하는 것은 반패턴입니다.

(내 것이 아님)


당신이 요청한 예제

그나저나 비동기/wait :D로 해결할 수 있는 예제 코드를 누군가 나에게 줄 수 있다면 좋을 것 같습니다.

예를 들어, 만약 당신이 정말로 그것을 하고 싶다면 (아마도 약간의 실수로, 지금 당장 확인할 수 없습니다, 부디 자유롭게 수정하세요)

// Warning, probable anti-pattern below
async myFunction() {
    const res1 = await this.serviceA.get().toPromise();
    const res2 = await this.serviceB.get().toPromise();
    const res3 = await this.serviceC.get().toPromise();
    // other stuff with results
}

동시에 할 수 에는,await Promise.all()어떤 통화도 서로의 결과에 의존하지 않기 때문에 더 효율적이어야 합니다.(원하는 대로forkJoin관찰 가능한 항목으로 수행)

async myFunction() {
    const promise1 = this.serviceA.get().toPromise();
    const promise2 = this.serviceB.get().toPromise();
    const promise3 = this.serviceC.get().toPromise();

    let res = await Promise.all([promise1, promise2, promise3]);

    // here you can retrieve promises results,
    // in res[0], res[1], res[2] respectively.
}

@Pac0에서 이미 다양한 솔루션에 대해 자세히 설명했듯이, 저는 약간 다른 각도를 추가할 것입니다.

약속과 관찰 가능한 항목의 혼합

저는 개인적으로 약속과 관찰을 섞지 않는 것을 선호합니다. 이는 비동기 대기를 관찰과 함께 사용하면서 얻게 되는 것입니다. 왜냐하면 그들은 비슷해 보이지만 매우 다르기 때문입니다.

  • 약속은 항상 비동기식이며, 관찰 가능 항목이 반드시 필요한 것은 아닙니다.
  • 약속은 하나의 값, 관측 가능한 값 0, 1 또는 여러 값을 나타냅니다.
  • 약속은 사용이 매우 제한적이므로 취소할 수 없습니다(ES 다음 제안은 제쳐두고). 관찰 가능한 것은 사용에서 훨씬 더 강력합니다(예를 들어 여러 WS 연결을 관리할 수 있습니다, 약속과 함께 사용해 보십시오).
  • API가 크게 다릅니다.

Angular에서의 약속의 사용

비록 때때로 두 가지 모두를 사용하는 것이 타당하지만, 특히 Angular를 사용하는 것은 가능한 한 RxJS로 가는 것을 고려해야 한다고 생각합니다.그 이유는 다음과 같습니다.

  • Angular API의 상당 부분은 관찰 가능한 것(라우터, http...)을 사용하므로 RxJS를 사용하여 스트림(펀을 의도하지 않음)과 함께 사용하지 않으며, 그렇지 않으면 RxJS가 제공하는 손실된 가능성을 보완하는 동안 항상 Promise로 변환해야 합니다.
  • 각진 힘이 있습니다.async파이프를 사용하면 필터링, 결합 및 수정 작업을 수행하는 스트림의 전체 응용 프로그램 데이터 흐름을 구성할 수 있습니다. 이 파이프를 사용하면 서버에서 들어오는 데이터 스트림을 중단하거나 구독할 필요가 없습니다.이렇게 하면 데이터 랩을 풀거나 보조 변수에 데이터를 할당할 필요가 없습니다. 데이터는 서비스에서 관찰 가능 항목을 통해 템플릿으로 바로 이동하기 때문에 매우 아름답습니다.

그래도 Promise가 빛날 수 있는 경우가 있습니다.예를 들어, rxjs TypeScript 유형에서 제가 누락한 것은 싱글의 개념입니다.다른 사용자가 사용할 API를 만드는 경우 관찰 가능을 반환하는 것이 다음과 같은 이점을 제공하는 것은 아닙니다.1개의 값을 받을 것입니까, 아니면 많은 값을 받을 것입니까, 아니면 단지 완료할 것입니까?당신은 그것을 설명하기 위해 댓글을 써야 합니다.반면에 Promise는 이 경우 계약이 훨씬 명확합니다.항상 1개의 값으로 해결되거나 오류와 함께 거부됩니다(물론 영원히 중단되지 않는 한).

일반적으로 프로젝트에 약속만 있거나 관찰 가능 항목만 있을 필요는 없습니다.어떤 것(사용자 삭제, 사용자 업데이트)이 완료되었음을 값으로 표현하고 이를 어떤 스트림에 통합하지 않고 대응하려면 Promise가 더 자연스러운 방법입니다.또한, 사용하기async/await에서는 코드를 순차적으로 작성할 수 있으므로 코드를 크게 단순화할 수 있으므로 들어오는 값에 대한 고급 관리가 필요하지 않으면 Promise를 그대로 유지할 수 있습니다.


예로 돌아가기

그래서 저는 RxJS와 Angular의 을 모두 받아들이는 것을 추천합니다.다시 예를 들어, 코드를 다음과 같이 작성할 수 있습니다(@Vayrex 아이디어에 대한 크레딧).

this.result$ = Observable.forkJoin(
  this.serviceA.get(),
  this.serviceB.get(),
  this.serviceC.get()
);

this.result$.subscribe(([resA, resB, resC]) => ...)

이 코드 조각은 3개의 요청을 실행할 것이며, 이러한 요청이 모두 완료되면, 관찰 가능한 항목은 다음으로 다시 호출됩니다.forkJoin 수 말한 처럼 수동으로 ) 할 수 .result$그리고.async파이프를 템플릿에 삽입합니다.

용사를 합니다.Observable.zip여기서 동일한 결과를 얻을 수 있을 것입니다, 사이의 차이.forkJoin그리고.zip관측치의 하고, 첫 두 번째 값을 입니다. 전 내 관 부 치 측 의 마 값 막 방 내 관 지 첫 의 치 측 후 부 즉 번 는 자 자 값 번 두 등 결 합 째 합 값 니 다 을 는 째 하 고 출 만 ▁is ▁that , ▁the ▁first ▁observ ▁only 즉 ▁the ▁inner 값 전 두


편집: 이전 HTTP 요청의 결과가 필요하므로,flatMap@Pac0의 답변에 접근합니다.

때부터toPromise2022년 현재는 더 이상 사용되지 않습니다.다른 사용법을 보여주고 싶습니다.awaitrxjs 파이프와 더 읽기 쉬운 합니다.저는 이 방법이 길고 복잡한 rxjs 파이프와 달리 훨씬 더 읽기 쉬운 코드를 만드는 것이라고 생각합니다.응답이 하나뿐이며 일반적으로 다른 작업을 수행하기 전에 응답을 기다리려고 하므로 특히 HTTP 요청에 유용합니다.


갱신하다

기능을 : 초기솔루작는동만지 rxjs기본동일기있능습다.firstValueFrom().

문서에서:

async function execute() {
  const source$ = interval(2000);
  const firstNumber = await firstValueFrom(source$);
  console.log(`The first number is ${firstNumber}`);
}

원본 솔루션

관찰할 수 있는 항목이 있으면 약속으로 요약하고, 구독하고, 구독이 실행될 때 해결할 수 있습니다.

getSomething(): Promise<any> {
    return new Promise((resolve, reject) => {
      this.http
        .get('www.myApi.com')
        .subscribe({
          next: (data) => resolve(data),
          error: (err) => reject(err),
        });
    });
  }

는 이제내서응수있다습니기다릴답 수 .async를 수행

  async ngOnInit() {
    const data = await this.getSomething();
    //Do something with your data
  }

이제 데이터에 대한 복잡한 작업을 많이 수행할 수 있으므로 rxjs 마법사가 아닌 사용자도 훨씬 더 쉽게 읽을 수 있습니다.서로 의존하는 세 개의 후속 http 요청이 있다면 다음과 같습니다.

  async ngOnInit() {
    const first = await this.getFirst();
    const second = await this.getSecond(first);
    const third = await this.getThird(second);
  }

관찰 가능한 항목은 스트림에 적합합니다(예: BehaviorSubject).그러나 데이터에 대한 단일 호출(예: http.get()))은 서비스 호출 자체를 비동기식으로 만드는 것이 더 나을 수 있습니다.

async getSomethingById(id: number): Promise<Something> {
    return await this.http.get<Something>(`api/things/${id}`).toPromise();
}

그런 다음 다음과 같이 간단히 부를 수 있습니다.

async someFunc(): Promise {
    console.log(await getSomethingById(1));
}

RxJS는 매우 강력하지만, 간단한 api 호출에 사용하는 것은 극단적인 오버킬처럼 보입니다.검색된 데이터를 마사지해야 하는 경우에도 getSomethingById 함수 내의 RxJS 연산자를 사용하여 최종 결과를 반환할 수 있습니다.

비동기/대기의 분명한 장점은 읽기가 더 명확하고, 호출을 체인으로 연결하기 위해 후프를 뛰어넘을 필요가 없다는 것입니다.

언급URL : https://stackoverflow.com/questions/49596641/is-it-a-good-practice-using-observable-with-async-await

반응형