Rxjs : Observable.combineLatest 대 Observable.forkJoin


84

Observable.combineLatest과의 차이점이 무엇인지 궁금 Observable.forkJoin하십니까? 내가 볼 수있는 한, 유일한 차이점은 forkJoinObservable이 완료 될 것으로 예상 combineLatest하고 최신 값 을 반환한다는 것입니다.


4
참고 : rxjs6에서 +이 이제 불과하다 combineLatest()forkJoin()관찰을 만드는 기능을한다. 동일하지만 구문이 다릅니다. 혼동하지 마십시오 combineLatest에서 rxjs/operators하는 것은 'pipeable'연산자입니다. 잘못된 것을 가져 오면 오류가 발생합니다.
Simon_Weaver

답변:


126

forkJoin모든 입력 관찰 가능 항목을 완료해야 할 뿐만 아니라 입력 관찰 가능 항목에 의해 생성 된 마지막 값의 배열 인 단일 값을 생성하는 관찰 가능 항목도 반환합니다. 즉, 관찰 가능한 마지막 입력이 완료 될 때까지 기다린 다음 단일 값을 생성하고 완료됩니다.

반대로 combineLatest모든 입력 관찰 가능 항목이 적어도 하나의 값을 생성하면 입력 관찰 가능 항목이 수행 할 때마다 새 값을 생성하는 Observable을 반환합니다. 이것은 무한한 값을 가질 수 있고 완전하지 않을 수 있음을 의미합니다. 또한 입력 관찰 가능 항목이 값을 생성하기 전에 완료 할 필요가 없음을 의미합니다.


@GregL forkJoin처럼 작동하지만 실패한 http 호출에서도 작동하는 함수가 있습니까?
Tukkan

2
@Tukkan, 오류에서 복구하는 연산자를 각 http 관찰 가능 항목에 연결하여 오류가 발생할 수있는 여러 관찰 가능 항목을 결합 할 연산자를 찾는 대신 오류 발생시 각 요청에 사용할 값을 정의합니다 (I 그런 연산자가 있는지 확실하지 않습니다). 오류에서 복구하는 연산자에는 .catch(), .onErrorResumeNext()및 가능 .retry()(Http 호출이 간헐적으로 실패 할 수있는 경우)이 포함됩니다.
GregL

1
명확히하기 위해 둘 다 배열을 생성합니다.
Simon_Weaver

@Simon_Weaver 반드시 그런 것은 아닙니다. 의 경우 combineLatest()프로젝션 함수를 제공하여 입력 관찰 가능 항목의 최신 값에서 출력 값을 생성하는 방법을 지정할 수 있습니다. 기본적으로 지정하지 않으면 최근 방출 된 값의 배열이 표시됩니다.
GregL

CombineLatest의 각 방출은 수집 된 값의 배열입니다. forkjoin에 대해서만 배열을 언급했기 때문에 추가하고 싶었습니다. 그래서 그들은 동일합니다. 그리고 예, RxJS에는 항상 미묘한 차이가 있으므로 내가 뭔가를 놓친 경우 당신이 의미하는 바를 명확히 할 수 있습니다.
Simon_Weaver

14

또한:

combineLatest (...)는 Observable을 순서대로 하나씩 실행합니다.

combineLatest내부적으로를 사용합니다 concat. 즉, 다음으로 이동하기 전에 배열의 각 관찰 가능 항목에 대해 값을 얻어야합니다.

// partial source of static combineLatest (uses the rxjs/operators combineLatest internally):
// If you're using typescript then the output array will be strongly typed based on type inference
return function (source) { return source.lift.call(from_1.from([source].concat(observables)), 
                           new combineLatest_1.CombineLatestOperator(project)); };

forkJoin (...)은 동시에 관찰 가능 항목을 병렬로 실행합니다.

소스 옵저버 블이 3 개 있고 각각 실행하는 데 5 초가 걸리면 실행하는 데 15 초가 걸립니다 combineLatest. 반면 forkJoin들이 병렬로 실행는 5 초 정도 걸릴 수 있도록.

따라서 주문이 시행되지 않는 곳 forkJoin과 다소 비슷 Promise.all(...)합니다.

오류 처리 고려 사항 :

Observable 오류가 발생 combineLatest하면 후속 항목이 실행되지 않지만 forkJoin모두 실행됩니다. 따라서 combineLatest관찰 가능 항목의 '시퀀스'를 실행하고 결과를 모두 함께 수집하는 데 유용 할 수 있습니다.


고급 참고 : 소스 Observable이 이미 '실행 중'(다른 항목에 의해 구독 됨)이고 사용중인 share경우이 동작이 표시되지 않습니다.

고급 참고 사항 : CombineLatest는 항상 각 소스의 최신 정보를 제공하므로 소스 Observable 중 하나가 여러 값을 방출하면 최신 정보를 얻을 수 있습니다. 각 소스에 대해 단일 값을 얻고 다음 소스로 이동하는 것이 아닙니다. 각 소스 Observable에 대해 '다음 사용 가능한 항목'만 가져 오도록해야하는 경우 .pipe(take(1))입력 배열에 추가 할 때 소스 Observable에 추가 할 수 있습니다 .


오류 처리를 고려해 주셔서 감사합니다. 여러 관찰 가능 항목의 경우 오류 처리를 이해하기가 매우 어렵습니다.
D Deshmane

2
나는 당신이 코드 concat()에서 무엇을하고 있는지 잘못 해석했다고 생각합니다 combineLatest(). Array.prototype.concatRxJS concat방법이 아닌 방법 처럼 보입니다 . 내가 옳다고 가정하면이 대답은 오해의 소지가 있고 부정확하며, combineLatest()Observable을 순서대로 하나씩 실행하지 않습니다. .NET과 동일하게 병렬로 실행합니다 forkJoin(). 차이는 생성되는 값의 수와 소스 관찰 가능 항목이 완료되어야하는지 여부에 있습니다.
GregL

@GregL Array.concat은 Observable에서 의미가 없습니다. 저는 concat의 순차적 인 특성에 절대적으로 의존합니다. 이해해야 할 핵심은 모두 실행될 때까지 출력 값을 얻지 못한다는 것입니다.
Simon_Weaver

귀하가 게시 한 샘플 소스 코드에서이 코드를 참조했습니다. [source].concat(observables)" combineLatest내부적으로 사용한다 concat" 는 말이 의미하는 바라고 가정합니다 . 배열 연결을 RxJS 연결과 혼동하는 것 같습니다. 후자는 실제로 입력 관찰 가능 항목을 순서대로 실행하고 각각이 완료 될 때까지 기다립니다. 그러나 그것은에서 사용되지 않으며 combineLatest()완전히 별개의 연산자입니다.
GregL

3
내가 생각 combineLatest()하고 forkJoin()모두 병렬로 실행합니다. 아래 코드를 실행하면 둘 다에 대해 약 5000이 출력됩니다. const start = new Date().getTime(); combineLatest([of(null).pipe(delay(5000)), of(null).pipe(delay(5000)), of(null).pipe(delay(5000))]).subscribe(() => console.log(new Date().getTime() - start)); forkJoin([of(null).pipe(delay(5000)), of(null).pipe(delay(5000)), of(null).pipe(delay(5000))]).subscribe(() => console.log(new Date().getTime() - start));
제레미

12

forkJoin- 모든 Observable이 완료되면 각각에서 마지막으로 방출 된 값을 내 보냅니다 .

CombineLatest -Observable이 값을 방출하면 각각의 최신 값을 방출합니다.

사용법은 매우 비슷하지만 forkJoin 과는 달리 combineLatest 구독을 취소하는 것을 잊지 마십시오 .


1
요청이 실패하면 중첩 된 모든 요청이 자동으로 취소되는 경우 어떻게 해결할 수 있습니까?
Sunil Garg

1
@SunilGarg 모든 결과 만 얻으려면 forkJoin 또는 combineLatest를 사용해야합니다. 모든 결과에 관심이 없다면 구독을 별도로 사용해야합니다.
Dmitry Grinko 19


구독 취소가 필요한 이유를 코드 예제로 설명해 주시겠습니까
Sunil Garg
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.