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.