【问题标题】:Get an observable item from observable list in `angular`从 `angular` 中的可观察列表中获取可观察项目
【发布时间】:2019-11-13 04:24:59
【问题描述】:

我在服务中有一个项目列表,以及一个将该列表包装在 observable 中的 getter。
observable 在带有async 管道的组件视图中使用,并按预期工作。当列表更新时,视图也会更新。

我还有一个不同的组件需要根据 id 从该列表中获取特定项目的 observable。
问题是具有该 id 的项目在被请求时可能尚未在列表中。 我怎样才能实现这一目标?

我尝试过的一些示例:

export class ItemsService {
  private itemList: Item[] = [];

  constructor() {
    // get the list from the backend    
  }

  // This is fine
  getItemList(): Observable<Item[]> {
    return of(this.itemList);
  }

  // This I assume does not work, because the pipe just applies map 
  //on whatever is now in the observable list
  getItem(id: string): Observable<Item> {
    return this.getItemList().pipe(map(items => items.find(item => item.id === id)));
  }

  // This I assume does not work as the local item is not yet set when I wrap it in an observable
  //to return it, and when it eventually gets set by the callback, it's already out of scope.
  // The weird thing to me is that the callback is only called at the beginning, when the list is empty,
  //and not anymore when the list gets populated
  getItem(id: string): Observable<Item> {
    let item: Item;
    this.getItemList().subscribe(items => {
      console.log('callback called');
      item = items.find(item => item.id === id);
    });
    return of(item);
  }
}

【问题讨论】:

  • 我们是否需要在 Angular 服务中有一个 subscribe() 代码块?

标签: angular rxjs observable


【解决方案1】:

当给定元素可用时获得通知的一种可能方法是使用主题。

将此添加到您的服务中:

private subject = new Subject<Item>();

收到数据后,循环遍历它并将其提供给主题。

  this.itemList.forEach((item: Item) => {
    this.subject.next(item);
  });

第三部分是获取通知。

  getItem(id: string): Observable<Item> {
    return this.subject
      .pipe(
        filter((item: Item) => item.id === id)
      )
  }

在您的组件中使用它,如下所示:

  ngOnInit() {
    const waitForElementWithId = 'b1';

    this.itemsService.getItem(waitForElementWithId).subscribe(x => {
      console.log(`${waitForElementWithId} is here`);
    });
  }

工作Stackblitz

【讨论】:

    【解决方案2】:

    试试这个:

    getItem(id: string): Observable<Item> {
      return this.getItemList().pipe(
        map(items => items.find(item => item.id === id)),
      );
    }
    

    【讨论】:

    • 抱歉,我的代码示例中的名称有误。我现在修好了。这是我已经尝试过的事情之一。
    • 那么你的消费者应该处理“未定义”的情况
    【解决方案3】:

    我同意你的看法。当您调用 getItemList() 时,您的 itemList 变量为空。 确保在 getItem() 中放置调试器并检查 itemList :

      getItem(id: string): Observable<Item> {
        let item: Item;
    
        console.log(this.itemList);
    
        debugger;
    
        // see whether itemList is empty or not;
        // if it's empty, the below function - getItemList() - return an observable with empty value.
    
        this.getItemList().subscribe(items => {
          console.log('callback called');
          item = items.find(item => item.id === id);
        });
        return of(item);
      }
    

    关键是包含 { return of(itemList) } 的 getItemList 不会监视 itemList 的新值。

    您可以改为使用 subject 并在从服务器获取数据完成后使用 next(data) 然后订阅该主题。

    【讨论】:

      猜你喜欢
      • 2021-12-28
      • 2018-04-11
      • 1970-01-01
      • 2018-07-09
      • 1970-01-01
      • 1970-01-01
      • 2013-04-26
      • 2018-11-18
      • 2013-08-24
      相关资源
      最近更新 更多