如何使用将可观察值映射到可观察值的对象的函数来映射可观察值?

时间:2018-08-19 00:36:07

标签: javascript rxjs observable

假设我有一个看起来像这样的函数:

const mapObservableToObject = o$ => ({
  counter: o$.pipe(
    pluck('values', 'counter')
  )
  username: o$.pipe(
    pluck('user', 'username'),
    map(sanitizeUsername)
  )
  input: unrelatedObservable$.pipe(
    pluck('target', 'value'),
    distinct(),
    auditTime(300)
  )
})

如何使用现有的可观察对象和类似函数创建新的可观察对象?新的可观察对象应发出形状为{ counter, username, input }的值,并带有其各自可观察对象的最新值,如果尚未接收到值,则默认为null。 (但可能是可选的默认值?)

2 个答案:

答案 0 :(得分:0)

尝试

const mapObservableToObject = o$ => ({
  counter: o$.pipe(
    pluck('values', 'counter'),
    startWith(null)
  )
  username: o$.pipe(
    pluck('user', 'username'),
    map(sanitizeUsername),
    startWith(null)
  )
  input: unrelatedObservable$.pipe(
    pluck('target', 'value'),
    distinct(),
    auditTime(300),
    startWith(null)
  )
})

const { counter, username, input } = mapObservableToObject(obs$);
combineLatest(counter, username, input).subscribe(v => console.log(v));

答案 1 :(得分:0)

我正在使用此自定义运算符,据我所知它应该为您解决问题,它与TypeScript的类型推断配合得很好:

  import { combineLatest, Observable } from 'rxjs';
  import { map } from 'rxjs/operators';

  /**
   * An equivalent of combineLatest, but using named arguments.
   */
  export const combineLatestToObject = <T>(
    source: { [P in keyof T]: Observable<T[P]> },
  ): Observable<{ [P in keyof T]: T[P] }> => {
    const keys = Object.keys(source);
    return combineLatest(keys.map(key => (source as any)[key])).pipe(
      map(values => {
        const result: { [key: string]: any } = {};
        for (const index in values) {
          result[keys[index]] = values[index];
        }
        return result;
      }),
    ) as any;
  };

对于发出任何东西之前的默认值,您可以根据需要添加startWith(null)publishBehavior(null)。另外,在代码中两次订阅o$时要小心-如果o$是可以观察到的多播,但要注意的话,就可以了。