簡體   English   中英

Rxjs - 將可觀察對象重新映射為值的對象

[英]Rxjs - remap object with observables as values

我得到了一個這樣的可觀察對象:

  const original = Observable.of({
    a: this.http.get('https://jsonplaceholder.typicode.com/todos/11'),
    b: this.http.get('https://jsonplaceholder.typicode.com/todos/22'),
    c: this.http.get('https://jsonplaceholder.typicode.com/todos/33')
  });

我需要解析內部可觀察對象並在訂閱處理程序中獲得類似這樣的內容:

  {
    a: ResponseFromServer,
    b: ResponseFromServer,
    c: ResponseFromServer,
  }

我應該如何處理這個問題?

謝謝。

編輯:我已經弄清楚了,請閱讀下文。

似乎沒有多少人知道 *Map 操作符曾經有一個叫做resultSelector的東西作為它們的第二個參數。 現在在 rxjs v6 中,你可以對inner map做同樣的事情,讓我告訴你。

const original = Observable.of({
    a: this.http.get('https://jsonplaceholder.typicode.com/todos/11'),
    b: this.http.get('https://jsonplaceholder.typicode.com/todos/22'),
    c: this.http.get('https://jsonplaceholder.typicode.com/todos/33')
});

const transformed = original.pipe(
    mergeMap(sourceValue => 
        forkJoin(_.values(sourceValue)).pipe(map(resolvedHttpRequests => {
            // here you have access to sourceValue as well as resolvedHttpRequests so you can do manual join to match the data.
        }))
    )
)

2020 年更新

forkJoin(
  // as of RxJS 6.5+ we can use a dictionary of sources
  {
    google: ajax.getJSON('https://api.github.com/users/google'),
    microsoft: ajax.getJSON('https://api.github.com/users/microsoft'),
    users: ajax.getJSON('https://api.github.com/users')
  }
)
  // { google: object, microsoft: object, users: array }
  .subscribe(console.log);

https://www.learnrxjs.io/learn-rxjs/operators/combination/forkjoin

他們上面的方式(使用Observable.of )本質上是創建一個由低級 Observable 組成的高級 Observable。

我認為更好的運算符是forkJoin ,因為這些 Observable 中的每一個都是冷的和有限的,並且forkJoin捕獲每個 Observable 的第一次發射並在所有值完成時發射所有值:

  const original = forkJoin([
    this.http.get('https://jsonplaceholder.typicode.com/todos/11'),
    this.http.get('https://jsonplaceholder.typicode.com/todos/22'),
    this.http.get('https://jsonplaceholder.typicode.com/todos/33')
  ]);

  let result = {a: null, b: null, c: null};

  original.subscribe([a,b,c] => result = {a,b,c});

請注意, forkJoin發出的項將是一個數組,其索引與傳入的 Observable 的索引相匹配。

如果源對象已經包含 Observables 你可以像下面這樣(顯然有多種方法可以做到這一點):

const mockXHRCall = (url: string) => {
  return of('response');
};

const original = of({
  a: mockXHRCall('https://jsonplaceholder.typicode.com/todos/11'),
  b: mockXHRCall('https://jsonplaceholder.typicode.com/todos/22'),
  c: mockXHRCall('https://jsonplaceholder.typicode.com/todos/33')
}).pipe(
  mergeMap(obj => {
    const observables$ = Object.keys(obj).map(key => obj[key].pipe(
      map(response => (
        { [key]: response } // wrap the response with eg. { c: ResponseFromC }
      )),
    ));

    return merge(...observables$);
  }),
  scan((acc, wrapped) => (
    { ...acc, ...wrapped }
  ), {}),
  takeLast(1),
).subscribe(console.log);

scan收集所有響應並將它們合並到一個對象中。

現場演示: https ://stackblitz.com/edit/rxjs-ffza8b

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM