2015-12-09 18 views
5

Mam Observable, w którym konsumuję kolejne obserwowalne, ale drugie Observable nie mogę rozwiązać. Oto kod:Jak rozwiązać problem z obserwowalności wewnątrz innego obserwowalnego? - rxjs

return Observable.fromPromise(axios(config)) 
     .map(res => { 
      return { 
       accessToken: res.data.access_token, 
       refreshToken: res.data.refresh_token     
      } 
     }) 
     .map(res => { 
      return { 
       me: getMe(res.accessToken), 
       accessToken: res.accessToken, 
       refreshToken: res.refreshToken     
      } 
     }) 

function getMe(accessToken) { 
    return Observable.fromPromise(axios.get({ 
     url: 'https://api.spotify.com/v1/me', 
    })); 
} 

Funkcja getMe zwraca Observable, ale nigdy nie został rozwiązany. Próbowałem dodać flatMap i concat, ale nadal nie został rozwiązany. Jak mogę rozwiązać problem z getMe?

Odpowiedz

8

Czy spróbować następujących (również niesprawdzone):

function getMe(accessToken) { 
    return Rx.Observable.fromPromise(axios.get({ 
    url: 'https://api.spotify.com/v1/me', 
    })); 
}  

Rx.Observable.fromPromise(axios(config)) 
    .map((res) => { 
     return { 
      accessToken: res.data.access_token, 
      refreshToken: res.data.refresh_token     
     } 
    }) 
    .flatMap((res) => { 
     return getMe(res.accessToken).map((res2) => { 
      res.me = res2; 
      return res; 
     } 
    }) 
    .subscribe((data) => console.log(data)); 

Jak wspomniano w powyższym poście, flatMap zwraca obserwowalne. map jest następnie używany do łączenia res z wynikiem res2 zwrócony z drugiej obietnicy.

Należy również pamiętać, że fromPromise można zaobserwować na zimno. Oznacza to, że musisz mieć abonament na inicjowanie rzeczy. W twoim przypadku, jak sądzę masz już coś takiego:

someFunction =() => { 
    return Rx.Observable.fromPromise(axios(config)) 
    ... 
    ... 
} 

someFunction.subscribe((data) => console.log(data)); 
+0

Interesująca propozycja. Może być wartościowy, aby go przetestować. Moim zdaniem możliwym problemem jest uzyskanie dostępu do 'res' z zamknięcia. Nie jestem tego pewien, ale anonimowa funkcja z 'res.ja 'w jego ciele, jest wykonywany/oceniany tylko wtedy, gdy' getMe' emituje wartość, w którym to momencie zastanawiam się, czy zmienna 'res' nadal utrzymuje swoją wartość. Koduję to defensywnie, używając wyłącznie czystych funkcji w połączeniu z obserwowalnymi. Więc chciałbym wiedzieć, czy jestem zbyt ostrożny. – user3743222

+0

Z perspektywy zamknięcia 'res' nadal będzie utrzymywał jego wartość (wcześniej użyłem tej techniki). Zgadzam się, że najlepiej jest mieć defensywny styl kodowania i dokładnie przetestować. Na marginesie, jeśli pojawi się drugie wykonanie 'Rx.Observable.fromPromise (axios (config))' zanim rozwiąże się 'getMe()', będziesz miał 2 egzekucje z subskrypcji. Można to łatwo naprawić za pomocą 'flatMapLatest', która zapewni, że zawsze otrzymasz najnowszą odpowiedź' getMe() 'z jednym wykonaniem subskrypcji. – Jeremy

+0

wystarczająco fair. Dziękuję za wyjaśnienie. – user3743222

0

Przykładowy kod do znalezienia poniżej (NIEBIESKI !!). Niektóre wyjaśnienia:

  • obserwowalny zwrócony przez getMe nie jest spłaszczony („postanowienie” należą do świata obietnic), ponieważ operator map nie spłaszczyć obserwable. flatMap zrobić, ale musisz go użyć w postaci source.flatMap(function(x){return observable}), a tutaj to, co zwrócisz, to POJO, a nie Rx.Observable.
  • Aby spłaszczyć getMe używamy flatMap.
  • Aby dodać z powrotem brakujące pola (accessToken i refreshToken) używamy withLatestFrom na obserwowalne który emitowany obiekt res (res$).
  • Używamy share, ponieważ subskrybujemy dwa razy do res$ i chcemy, aby wszyscy subskrybenci zobaczyli te same wartości.

    var res$ = Observable 
        .fromPromise(axios(config)) 
        .map(function (res) { 
         return { 
         accessToken : res.data.access_token, 
         refreshToken : res.data.refresh_token 
         } 
        }) 
        .share(); 
    var getMe$ = res$.flatMap(function (res) {return getMe(res.accessToken)}); 
    var finalRes$ = getMe$.withLatestFrom(res$, function (getMe, res) { 
    return { 
        me   : getMe, 
        accessToken : res.accessToken, 
        refreshToken : res.refreshToken 
    } 
    }); 
    
    function getMe (accessToken) { 
        return Observable.fromPromise(axios.get({url : 'https://api.spotify.com/v1/me'})); 
    } 
    
+0

POJO = Plain Old JavaScript Object – user3743222

+0

dziękuję za pomoc, ale to wydaje się bardziej zawiłe niż przy użyciu 'Promises'. Musi być bardziej zwięzły. – jhamm

+0

Pewnie zobaczmy, co inni wymyślą. Pytanie: dlaczego nie używasz obietnic, a następnie przekształcasz je w obserwowalne, gdy osiągniesz pożądany rezultat? 'Rx.Observable.fromPromise' robi to, dzięki czemu masz najlepsze z obu światów. – user3743222

2

Jako @ user3743222 wskazał, Observable nie resolve w tym sensie, że Promise robi. Jeśli chcesz uzyskać wartość z metody getMe, musisz zasubskrybować zwracaną przez siebie wartość Observable.

return Observable.fromPromise(axios(config)) 
     .map(res => { 
      return { 
       accessToken: res.data.access_token, 
       refreshToken: res.data.refresh_token     
      } 
     }) 
     .flatMap(function(tokens) { 

      //FlatMap can implicitly accept a Promise return, so I showed that here 
      //for brevity 
      return axios.get({url : 'https://api.spotify.com/v1/me'}); 
     }, 

     //The second method gives you both the item passed into the first function 
     //paired with every item emitted from the returned Observable` 
     //i.e. axios.get(...) 
     function(tokens, response) { 
      return { 
      accessToken: tokens.accessToken, 
      refreshToken: tokens.accessToken, 
      //Here response is a value not an Observable 
      me: response 
      }; 
     }); 
Powiązane problemy