【问题标题】:Return object from observable inside another observable从另一个可观察对象中的可观察对象返回对象
【发布时间】:2017-07-12 10:46:36
【问题描述】:

我尝试从 3 个不同的 REST 端点获取数据。数据模型由主要数据组成,并具有带有 2 个(将来可能更多)对象的高级数组。我想根据每个高级对象中指定的 REST 端点向每个高级对象中注入一个带有选项的数组。一切正常,并且作为对象从 Observable 返回,除了附加的选项,作为 Observables 出现。

简化数据:

{
 simple: {
   param: "searchQuery",
 },
 advanced: [
  {
   param: "food",
   optionsModel: {
     url: "http://address.com/food",      
     }
  },
  {
   param: "drinks",
   optionsModel: {
     url: "http://address.com/drinks",
     }
   }
  ]
}

食物和饮料具有相同的结构,由具有名称和 ID 的对象组成:

 {
  data: [
   {
     name: "DR1",
     id: 1
   },
   {
     name: "DR2",
     id: 1
   },
   ...
  ]
 }

在我的数据模型中,我没有 options[] 数组,所以我手动注入它。服务:

 searchConfiguration$: Observable<SearchConfiguration> = this.http
  .get(this._configURL)
  .map((config) => {
      let configuration = config.json();
      let advancedArray = configuration.advanced;

      if(advancedArray) {
        advancedArray.forEach(advanced => {
          advanced.options = [];
          advanced.options = this.http.get(advanced.optionsModel.url)
             .map((r: Response) => r.json().data
        })
      }
    return configuration;
  })

父组件:

getSearchConfig() {
  this.searchConfiguration$ = this._bundlesService.searchConfiguration$;
} 

然后我在 html 中有异步管道来订阅 Observable。如何将我的选项作为实际数组而不是作为流附加到高级?

编辑 - 解决方案

感谢马丁的回答,解决方案是展平两个流,最后用 forkJoin() 连接它们

  searchConfiguration$: Observable<SearchConfiguration> = this.http
  .get(this._configURL)
  .map((config) => config.json())
  .concatMap((configuration) => {
      let observables = configuration.advanced.map((advanced) => {
        return this.http.get(advanced.optionsModel.url)
          .map((r: Response) =>  r.json().data)
          .concatMap((options) => advanced.options = options)
      });
    return Observable.forkJoin(observables, (...options) => {
      return configuration;
    })
  });

【问题讨论】:

    标签: javascript angular rxjs observable rxjs5


    【解决方案1】:

    我没有测试它,但我认为你可以如下:

    searchConfiguration$: Observable<SearchConfiguration> = this.http
      .get(this._configURL)
      .map((config) => config.json())
      .concatMap(configuration => {
        var observables = configuration.advanced.map(advanced => {
          return this.http.get(advanced.optionsModel.url)
             .map((r: Response) => r.json().data);
        });
    
        return Observable.forkJoin(observables, (...options) => {
          configuration.options = options;
          return configuration;
        });
      })
    

    【讨论】:

    • 这对我有很大帮助,我得到了所有高级选项,问题是我想让它们附加到整个对象 - 其中.map((config) =&gt; config.json().advanced) 直接映射到高级。
    • @Tina333 啊,我明白了。然后它变得有点复杂。我正在使用forkJoin() 等到所有this.http 完成,然后用它们的结果更新configuration
    • 非常感谢,我设法解决了。所以是我错误地解释了我想要的 - 根据每个 url 将每个选项数组附加到每个高级对象(而不是整个对象,正如我解释的那样)。我设法通过在observables. 上添加一个 concatMap() 到您的建议来做到这一点。我在问题中添加了修改后的代码。
    猜你喜欢
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 2022-08-19
    • 1970-01-01
    • 2018-12-16
    • 1970-01-01
    相关资源
    最近更新 更多