简体   繁体   English

Rxjs - 将可观察对象重新映射为值的对象

[英]Rxjs - remap object with observables as values

I got an observable like this:我得到了一个这样的可观察对象:

  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')
  });

I need to resolve the inner observables and get something like this in the subscribe handler:我需要解析内部可观察对象并在订阅处理程序中获得类似这样的内容:

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

How should I approach this problem?我应该如何处理这个问题?

Thanks.谢谢。

EDIT: I've figured it out, read below.编辑:我已经弄清楚了,请阅读下文。

It seems that not many people know that *Map operators used to have something called resultSelector as their second argument.似乎没有多少人知道 *Map 操作符曾经有一个叫做resultSelector的东西作为它们的第二个参数。 Now in rxjs v6, you can do the same with inner map , let me show you.现在在 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.
        }))
    )
)

Update for 2020 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 https://www.learnrxjs.io/learn-rxjs/operators/combination/forkjoin

They way you're doing it above (with Observable.of ) is essentially creating a higher-level Observable of lower Observables.他们上面的方式(使用Observable.of )本质上是创建一个由低级 Observable 组成的高级 Observable。

I think a better operator would be forkJoin , as each of these Observables are cold and finite and forkJoin captures the first emission of each Observable and emits all values when all are complete:我认为更好的运算符是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});

Just note that the emitted item from forkJoin will be an array whose index match the indices of the Observables passed in.请注意, forkJoin发出的项将是一个数组,其索引与传入的 Observable 的索引相匹配。

If the source object already contains Observables you can do it for example like the following (there are obviously multiple ways to do this):如果源对象已经包含 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);

The scan collects all responses and merges them into a single object. scan收集所有响应并将它们合并到一个对象中。

Live demo: https://stackblitz.com/edit/rxjs-ffza8b现场演示: https ://stackblitz.com/edit/rxjs-ffza8b

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 RxJS Observables:用值创建 - RxJS Observables: Creating with values 结合RxJS可观察对象并基于通用对象属性值进行合并,映射 - Combining RxJS observables and merge, map based on common object property values Angular 8 rxjs从多个可观察对象获取值 - Angular 8 rxjs get values from multiple observables 在对对象进行操作时链接递归 RxJS observables - Chaining recursive RxJS observables while operating on object 是否可以使用Rxjs库中的Observables of()符号返回多个值? - Is it possible using Observables of() symbols from Rxjs libary to return multiple values? Rxjs:使用 function 中的 observable 值返回 promise/observable - Rxjs: use values of observables in function that return promise/observable Angular 9 rxjs - forkJoin 返回 Observables 数组而不是值数组 - Angular 9 rxjs - forkJoin returns array of Observables instead of array of values RxJS Observables-多个订阅者获得对同一对象的引用 - RxJS Observables - multiple subscribers getting reference to same object 返回由两个不同的 Observable 组成的合并对象,这些 Observable 依赖于 RxJS - Return a merged object composed by two different Observables with dependencies with RxJS 如何使用 rxjs Observables 处理可能是空对象的 API 响应? - How to handle an API response that might be an empty object with rxjs Observables?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM