【问题标题】:Angular Observable Array Object ConversionAngular Observable 数组对象转换
【发布时间】:2018-07-08 16:05:28
【问题描述】:

所以我已经阅读了许多关于 Javascript/Angular 中的项目转换的 SO 问题,但没有找到任何可以解决我的问题的内容。我从 Firestore 中提取一个可以有副本的对象。然后我需要使用 1 到多个转换来转换对象。来自 Firestore 的对象是“MultipleCard”。这个“MultipleCard”有一个名为“copies”的属性,用于表示应该创建多少“Cards”。

  postsCol: AngularFirestoreCollection<MultipleCard>;
  posts: Observable<MultipleCard[]>;

  cardsListObservable: Observable<Card[]>; //Not sure which to use
  cardsList: Card[]; //Not sure which to use

  constructor(private messageService: MessageService,
              private db: AngularFirestore) {
    this.messageService.add('Fetching cards');

    this.postsCol = this.db.collection('cards');
    this.posts = this.postsCol.valueChanges();

 //?? Nothing I do here seems to work correctly. Most operations act on the array itself or do a 1 to 1 conversion
}

组件

<mat-list *ngFor="let card of cardsList | async"> //Or cardsListObservable
  <mat-list-item>{{card.name}}</mat-list-item> 
 </mat-list>

如何将 Observable 转换为 Observable 或 Card[]?例如,我可能有一个包含以下“MultipleCard”的数组

 [{ id: 1,
     copies: 3},
    {id: 2, copies:1}]

这应该被转换成一个由 4 个“卡片”对象组成的数组:

[{ id: 1, copyVersion:1},
    { id: 1, copyVersion:2}.
    { id: 1, copyVersion:3},
     { id: 2, copyVersion:1}]

感谢任何见解!

编辑 1

尝试了以下方法:

this.posts.subscribe((posts) => {
  posts.forEach( post => {
    console.log(post);
    this.cardsList.push(post);
  });
});

但是得到:

core.js:1350 错误类型错误:无法读取未定义的属性“推送” 在 eval (deck-list.component.ts:40)

最终更新代码:

  static fromMultiple(multipleCard: MultipleCard): Card[] {
    const data: Card[] = [];
    for (let i = 0; i < multipleCard.copies; i++) {
      data.push(new Card(multipleCard));
    }
  return data;

}

this.postsCol = this.db.collection('cards');
this.posts = this.postsCol.valueChanges();

this.posts.subscribe((posts) => {
  posts.forEach( post => {
    const temp = Card.fromMultiple(post);
    temp.forEach(tempCard => {
      this.cardsList.push(tempCard);
    });
  });
});

【问题讨论】:

  • 实际的问题/问题是什么?
  • @Zze 更新了问题的简化版本
  • 显示您的服务代码?
  • @Haris 你指的是什么服务代码?我正在使用 AngularFirestore 数据库将对象拉到我上面发布的类中。
  • 您可以使用map 将您的可观察对象转换为发出一个数组,而不是任何火力基地返回。即this.posts = this.postsCol.valueChanges().map(x =&gt; /*do stuff here*/)。此外,您应该使用带有 observable 的异步管道,即posts ({{ posts | async }})。在你的地图函数中放置一个断点 - 调试是你的朋友。

标签: angular typescript rxjs google-cloud-firestore


【解决方案1】:

您可以在集合上使用 valueChanges()snapshotChanges() 从您的请求中返回 Observable。

这里是valueChanges()的例子:

this.posts = this.db.collection<MultipleCard[]>('posts').valueChanges();

所以此行返回一个Observable&lt;MultipleCard[]&gt;,然后您可以订阅并接收 MultipeCard[] 数组,如下所示:

this.posts.subscribe((posts) => {
   console.log(posts); //This is the array of posts, not an observable
 });

您不需要在组件中手动订阅它,因为这就是 ASYNC 管道在标记中为您所做的事情。你可以像*ngFor="let post of (posts | async)"那样在你的标记中设置你的forLoop,这也将开始订阅你的Observable数据,并在这个组件被销毁时关闭订阅。我希望这能有所帮助!

您应该对 Observable 数据和正在使用的 rxjs 库进行更多研究,因为它可以让您更深入地了解您从 firebase(特别是 firestore)处理的数据。

【讨论】:

  • 查看我的编辑。这让我非常接近,但仍然存在问题。我想我以前试过这个,但遇到了同样的错误......
  • 忽略,我从未初始化我的数组cardsList:MultipleCard[] = [];
  • 我知道你在那里做了什么,但只是在你 forEach 你的帖子数组然后将每个项目推入 cardList 数组之后,你有两个完全相同的数组。 forEach 和 push 是多余的,因为您只是在重新创建相同的数组。你可以做this.cardsList = posts;
  • 是的,我跳过了我将进行对话并推送多个对象的部分。关键是订阅部分与 for each 循环相结合。
  • this.db.collection 给 Observable 一个数组数组。现在应该是 this.db.collection.
【解决方案2】:

你要么订阅你的 observable 流,要么承诺它,看看你得到了什么。假设一个函数 getData() 返回一个 observable,你可以这样做

getData().subscribe((card: any) => * do something *) 

getData().toPromise().then((card: any) => * do something*)  

我建议这样做并登录响应(此处为卡片)。这样你就会知道发生了什么。

【讨论】:

    猜你喜欢
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    • 2019-07-05
    • 2021-05-23
    • 1970-01-01
    • 2020-10-14
    相关资源
    最近更新 更多