2016-11-06 9 views
5

중첩 된 관측 가능 지옥에 갇혀 있고 손으로 할 수 있습니다.중첩 된 관측 가능 개체를 좁히기

나는 다음과 같은 코드 블록

return this.findUser(term).map(users => { 
    return users.map(user => this.getLastLogin(user.user_id).map(last_login => { 
    user.last_login = last_login; 
    return user; 
    })); 
}); 

findUser 반환 Observable<User[]>getLastLogin 반환 Observable<number> 있습니다.

기본적으로 사용자 목록을 가져 와서 다른 값의 정보로 업데이트하려고합니다.

지금 위의 코드는 <Observable<Observable<User>[]>을 반환합니다.

mapflatMap으로 바꿀 수 있다고 생각했지만이 경우 개체가 <Observable<Observable<User>>으로 바뀝니다.

RxJS 문서 그래서 나는 내가 필요로 저를 얻을 것이다 switch, forkJoin 또는 flatMap 어떤 조합 모르겠어요 해독 조금 어렵습니다.

나는 Observable<User[]>을 반환하고 싶습니다. 누구든지 올바른 방향으로 나를 가리킬 수 있을까요?

답변

4

는 사실, 당신이 forkJoin()switch()가이 작업을 수행 할 필요가 없습니다.

일반적으로 다른 비동기 호출로 사용자 배열의 각 사용자를 업데이트하려고합니다.

나는 이런 식으로 할 거라고 :

var source = findUser('term') 
    .mergeAll() 
    .mergeMap(user => getLastLogin(user.user_id) 
     .map(last_login => { 
      user.last_login = last_login; 
      return user; 
     }) 
    ) 
    .toArray(); 

source.subscribe(val => console.log(val)); 

운영자 mergeAll()은 하나의 관찰 가능한으로 관찰 가능한 높은 순서로 변환합니다. 이 경우 모든 사용자의 배열을 가져 와서 하나씩 다시 방출합니다. 그런 다음 mergeMap()last_login 날짜로 업데이트 된 사용자를 방출합니다. 결국 toArray()을 사용하여 단일 사용자를 전체적으로 방출되는 하나의 큰 배열로 변형 시켰습니다. 대신 단일 사용자를 방출하려는 경우이 연산자를 제거 할 수 있습니다.

return users.map(...)을 사용했을 때 배열을 반환하는 Array.map()을 사용하고 Observable을 반환하는 RxJS에서 map()을 사용하지 않았습니다. 단일 객체로 작업하는 것이 일반적으로 객체 배열을 사용하는 것이 더 쉽다고 생각합니다. 질문의 제목이 중첩 된 관찰 가능한 평탄화 언급 특히 - - 나는 당신이 깔끔한 대답이라고 생각

[ { name: 'foo', 
    user_id: 42, 
    last_login: 2016-11-06T10:28:29.314Z }, 
    { name: 'bar', 
    user_id: 21, 
    last_login: 2016-11-06T10:28:29.316Z } ] 
+0

하지만 난 여부에 관해서 궁금 : https://jsbin.com/naqudun/edit?js,console

이 인쇄 콘솔로 :

라이브 데모를 참조하십시오 배열 순서는 항상 소스 배열의 배열 순서와 일치합니다 :'mergeMap'을 사용하면 비 결정적 순서로 결과가 나타 납니까? 순서가 병합 된 관찰 대상이 먼저 출현하는지에 달려 있습니까? – cartant

+1

이것은 사실입니다.'merge' 나'mergeAll'은 같은 순서를 보장 할 수도 있고 그렇지 않을 수도 있습니다.그러나 문제가된다면'mergeMap'을'concatMap'으로 대체하면됩니다. – martin

+1

흥미롭게도이 코드는 TypeScript의 클래스를 사용할 때는 작동하지 않습니다. 컴파일 할 때'findUsers' 메쏘드에서'mergeAll'이'User []'를 리턴하는 것처럼 보입니다. 여기 내가 보는 행동에 대한 링크가 있습니다. https://jsbin.com/wiwayikiye/edit?js,console 아이디어가 있습니까? – user3750194

1

하나 개의 솔루션은 사용자에게 getLastLogin에 호출의 결과에 가입 forkJoin를 사용하고지도하는 것입니다 :

// forkJoin will return Observable<User[]>, so use switchMap. 

return this.findUser(term).switchMap(users => Observable.forkJoin(

    // Map the array of users to the array of observables to be joined. Use 
    // first to ensure the observables complete. 

    users.map(user => this.getLastLogin(user.user_id).first()), 

    // Use forkJoin's selector to add the last_login to each user and return 
    // the users. 

    (...logins) => { 
    users.forEach((user, index) => { user.last_login = logins[index]; }); 
    return users; 
    } 
)); 
관련 문제