【问题标题】:Pipe Observable subscription with map angular使用地图角度的管道可观察订阅
【发布时间】:2019-10-31 18:08:05
【问题描述】:

其实我想调用另一个以数组值作为参数的函数。我正在从一个主题中获取数组:

this.shopService.$getShops().pipe(map(
  shops => {
    console.log(shops[0]);
  }
)).subscribe();

订阅基于此:

      private newShopsSubj = new BehaviorSubject(undefined);

  setShops(shops: any) {
    this.newShopsSubj.next(shops);
  }


  $getShops(): Observable<any> {
    return this.newShopsSubj.asObservable();
  }

实际上代码正在运行...但是console.log 调用以undefined 结束。不知何故,我找不到合适的解决方案。

我想做这样的事情:

   this.shopService.$getShops().subscribe(resp => {
this.shopService.getProductsByShopID(resp[0].id).subscribe(resp
=> {do something...};});

但它实际上失败了,因为resp[0].id 保持在undefined... 我对地图的尝试失败了。

非常感谢任何帮助...

谢谢

胡乔

【问题讨论】:

  • 尝试更改第二个“resp”参数名称。相反,尝试结果......只是为了区分这两个参数。
  • 不幸的是不是......异步时间是问题所在。我不明白为什么在得到主题响应之前,内部函数会以某种方式过早地被触发......

标签: angular pipe observable


【解决方案1】:

与其他答案一样...如果在设置值之前调用$getShops(),您将获得undefined,因为这是初始值。可以将其初始化为空数组,也可以使用 rxjs filter 过滤掉 undefined 的值。此外,我会将这些请求链接到例如switchMapmergeMap,因为不建议嵌套订阅。所以我建议如下:

private newShopsSubj = new BehaviorSubject([]);
public newShopsSubj$ = this.newShopsSubj.asObservable();

及组件代码:

import { mergeMap, filter } from 'rxjs/operators';
import { of } from 'rxjs';

// ...

this.shopService.newShopsSubj$.pipe(
  mergeMap((shops: any[]) => {
    // do a check that that there is an object
    if (shops && shops.length) {
      return this.shopService.getProductsByShopID(shops[0].id)
    }
    // no shops, so return...
    // empty array, since assuming the above function returns array of products
    return of([]);
  })
).subscribe((products: any[]) => {
  // check if products exist and do your magic!
})

或如前所述,将您的 BehaviorSubject 初始值设置为 undefinedfilter 远离这些值:

this.shopService.newShopsSubj$.pipe(
  filter(shops => !!shops)
  mergeMap((shops: any[]) => {
  // .....

请注意,我在这里使用了any。不要使用它。将您的数据输入模型! (我更喜欢接口)。

记得在OnDestroy退订!!

【讨论】:

  • 感谢您提供全面的解决方案!
  • 非常欢迎您,希望它有助于解决您的问题 :)
【解决方案2】:

BehaviourSubject 将当前值发送给新订阅者。

这里你用undefined初始值初始化它

private newShopsSubj = new BehaviorSubject(undefined);

所以当你像下面这样订阅它时

  this.shopService.$getShops().subscribe(resp => {
this.shopService.getProductsByShopID(resp[0].id).subscribe(resp
=> {do something...};});

最初,它会将resp 视为未定义。 要解决此问题,您可以使用 Subject 而不是 BehaviorSubject 或使用适当的商店对象初始化 BehaviourSubject

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 2021-11-14
    相关资源
    最近更新 更多