【问题标题】:How to properly get array data from observable?如何从 observable 中正确获取数组数据?
【发布时间】:2019-09-23 15:00:33
【问题描述】:

我需要两个函数来返回所有数据以及特定的过滤数据,但我的构造是错误的。以下是我想要的“想法”,但返回的是订阅而不是数组:

   allItems() {

      var collectionAll: AngularFirestoreCollection<Item> =
         this._afs.collection<Item>('items');

      var itemArray$: Observable<Item[]> =
         collectionAll.valueChanges();

      // Returns Subscription but I need Items[]
      return itemArray$.subscribe(items => {
         return items;
      })
   }

   specificItems(name: string) {

      var collectionSpecific: AngularFirestoreCollection<Item> =
         this._afs.collection<Item>('items', ref =>
            ref.where('name', '==', name));

      var itemArray$: Observable<Item[]> =
         collectionSpecific.valueChanges();

      // Returns Subscription but I need Items[]
      return itemArray$.subscribe(items => {
         return items;
      })
   }

我还认为它需要是一个异步函数,但订阅函数不会返回一个承诺。

我什至不确定什么时候会从 Firestore 向我收取读取计数...?

【问题讨论】:

标签: javascript angular firebase google-cloud-firestore angularfire2


【解决方案1】:

如果你想要一个 Promise,你需要使用 toPromise 将 Observable 转换为 Promise:

specificItems(name: string): Promise<Item[]> {
  var collectionSpecific: AngularFirestoreCollection<Item> =
     this._afs.collection<Item>('items', ref =>
        ref.where('name', '==', name));

  var itemArray$: Observable<Item[]> =
     collectionSpecific.valueChanges();

  return itemArray$.toPromise();
}

【讨论】:

  • 安德烈,这确实回答了我的问题,所以我接受了你的回答。我认为虽然我可能有错误的方法首先引发了这个问题(对 Maryannah 的回应)。不过谢谢。
【解决方案2】:

Observables 非常强大,你应该保持原样。

allItems = this._afs.collection<Item>('items').valueChanges();

在您的模板中,您可以简单地使用异步管道来读取您的数据:

<div *ngFor="let items of allItems | async">...</div>

这是使用 Angular 最强大的方式有几个原因,所以请尽快尝试学习它,因为基本上 Angular = RxJS(当然不是真的,但它告诉你在 Angular 中你需要多少 RxJS)

【讨论】:

  • Observables 对我来说仍然是一种思维转变。 ;) 它们可以用来添加吗?在我的示例中,我打算创建一个项目数组,然后在用户会话期间添加到其中(获取所有名为“ABC”的项目,然后添加“DEF”等)。这可能使用 Observables 吗?正如 Andrei 指出的那样,更改为 promise 会得到数组,但也许我的方法不正确?
  • Observables 是增强的 Promise,Promise 能做什么,他们可以做得更好。任何告诉您否则的人都不了解可观察对象。而他的解决方案只是返回一个承诺,它没有返回一个可观察的。使用 async 关键字可以。但是鉴于 JS 有一个线程,这意味着您在调用期间阻塞它。我不会说这是不好的做法,但绝对不是好做法。
  • @LovetoCode 哦,对于 firebase 的读取计数,一个请求 = +1。您每月有 30k 次操作,所以应该没问题!
【解决方案3】:

在不同的位置声明以下模型,以便您可以重复使用相同的模型。

  export class EmployeeRoster {
        RosterDate: Date;
        EmployeeId: number;
        RosterDayName: string;
        ProjectId: number;
        ShiftId: number;
        ShiftTime: string;
        ShiftColor: string;
        IsOnLeave: boolean;
    }

在您的服务层中声明以下方法。

      GetSavedEmployeeData(empIds: EmployeeIdlistToRoster[], sDate: string, eDate: string): Observable<EmployeeRoster[]> { 
        let empIdsValue = '';
        if (empIds !== null && empIds.length > 0) {
          empIds.forEach(function (em) {
            empIdsValue += em.EmpId + ',';
          });
        }

        //How to pass value as a parameter
        const paramsdsf = new HttpParams()
          .set('empIds', empIdsValue)
          .append('sDate', sDate)
          .append('eDate', eDate);
        return this.http.get<EmployeeRoster[]>(apiUrl, { params: paramsdsf });
      }

这只是一个示例,您可以根据需要更新此方法和模型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-23
    • 1970-01-01
    • 2021-06-11
    • 2020-10-02
    • 2021-08-03
    • 1970-01-01
    • 2020-08-02
    相关资源
    最近更新 更多