简体   繁体   English

AngularFire firestore get / snapshotchanges / valuechanges 对 observable 的操作不是异步的?

[英]AngularFire firestore get / snapshotchanges / valuechanges action on observable is not async?

Hi I am having a very strange behaviour.嗨,我有一个非常奇怪的行为。

I am iterating over some documents and setting some promises that when the documents are fetched the UI is updated.我正在遍历一些文档并设置一些承诺,即在获取文档时更新 UI。

However, while the promises are atomic, the firestore / AngularFire waits for all the promises.然而,虽然承诺是原子的,但 firestore / AngularFire 等待所有的承诺。

Example:例子:

 for (const event of events) {
        this.eventService.getEventActivitiesAndSomeStreams(this.user,
          event.getID(),
          [DataLatitudeDegrees.type, DataLongitudeDegrees.type])
          .pipe(take(1)).toPromise().then((fullEvent) => {
            this.logger.info(`Promise completed`)
           
          })
      }

One would expect that slowly for each promise as the data comes it would print the promise completed.人们会期望随着数据的到来,对于每个 promise 都会慢慢打印 promise 完成。

However they are all printed as once.但是,它们都打印一次。 It doesn't look that those promises come one by one but "all at once".看起来这些承诺并不是一一兑现的,而是“一下子”兑现的。 There is a big waiting time till the first console log is printed and then all promises print that.在打印第一个控制台日志之前有很长的等待时间,然后所有的承诺都打印出来。

So I would expect if I have a progress bar to increase little but little but increases at once所以我希望如果我有一个进度条增加一点但很少但立即增加

The inner call this.eventService.getEventActivitiesAndSomeStreams内部调用this.eventService.getEventActivitiesAndSomeStreams

return this.afs
        .collection('users')
        .doc(userID)
        .collection('events')
        .doc(eventID)
        .collection('activities')
        .doc(activityID)
        .collection('streams', ((ref) => {
          return ref.where('type', 'in', typesBatch);
        }))
        .get()
        .pipe(map((documentSnapshots) => {
          return documentSnapshots.docs.reduce((streamArray: StreamInterface[], documentSnapshot) => {
            streamArray.push(this.processStreamDocumentSnapshot(documentSnapshot)); // Does nothing rather to create an class of the JSON object passed back from the firestore
            return streamArray;
          }, []);
        }))

Now, if I put an await inside the for loop of course this works as it should going and completing the promises as it should, but then it takes a lot of time.现在,如果我将 await 放在 for 循环中,当然这会按预期进行并按预期完成承诺,但这会花费很多时间。

I also tried to not use AngularFire and use the native JS SDK with the same effect.我也尝试过不使用 AngularFire 并使用原生 JS SDK 具有相同的效果。

I am suspecting that the IndexedDB can be causing this or some other Firebase logic.我怀疑 IndexedDB 可能导致这个或其他一些 Firebase 逻辑。

What am I missing here, and how can I have the desired behaviour if possible?我在这里错过了什么,如果可能的话,我怎样才能得到想要的行为?

You could repro this via a ["users" -> "events" -> "something"] firestore collections, were each "user" has lets say 500 "events" and each of those events has 2 more docs.您可以通过 ["users" -> "events" -> "something"] firestore collections 重现这一点,假设每个“用户”都有 500 个“事件”,并且每个事件都有 2 个文档。

So get all the events for the user and try to make for each one a promise that will return 2 documents of "something" inside a for array )因此,为用户获取所有事件,并尝试为每个事件创建一个 promise,它将在 for 数组中返回 2 个“某物”文档)

This behavior is pretty expected and has nothing at all to do with firebase. you're iterating over an array and sending out requests.这种行为是意料之中的,与 firebase 没有任何关系。您正在遍历数组并发送请求。 there is no waiting or delay between items, so the for loop (without await statements) will finish in an imperceptibly small amount of time, which means all of the requests are being sent out within milliseconds of each other, or basically at the same time.项目之间没有等待或延迟,因此 for 循环(没有 await 语句)将在极短的时间内完成,这意味着所有请求都在彼此之间的毫秒内发送,或者基本上是同时发送. So their responses should be expected to arrive at basically the same time as well.因此,他们的回复应该也基本同时到达。

You've stated that you don't want to use await statements and iterate one by one, so it's tough to know exactly what you do want or expect to happen.您已经声明您不想使用 await 语句并逐个迭代,因此很难确切地知道您想要或期望发生什么。 maybe you want them to be spaced.5 second apart?也许您希望它们间隔 5 秒? If so, you need to write that logic:如果是这样,您需要编写该逻辑:

timer(0, 500).pipe( // put whatever ms time between requests you want here?
  take(events.length),
  switchMap(i => {
    return this.eventService.getEventActivitiesAndSomeStreams(this.user,
      events[i].getID(),
      [DataLatitudeDegrees.type, DataLongitudeDegrees.type]).pipe(take(1))
  })
).subscribe(fullEvent => {
  this.logger.info(`Promise completed`)
})

(removed promises cause idk why they're being used in the first place and this kind of control is easier with rxjs IMO) (删除承诺会导致 idk 为什么首先使用它们,并且使用 rxjs IMO 可以更轻松地进行这种控制)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 具有活动 valueChanges 侦听器的 Firestore 限制 - Firestore limitations with active valueChanges listeners 带有 idField 和不存在文档的 AngularFire valueChanges - AngularFire valueChanges with idField and non-existent document Angular/angularfire2 - 读取可观察文档并将数据保存到 object。无异步 pipe - Angular/angularfire2 - Read a document observable and save the data to an object. No async pipe 如何从 angularfire 获取变量,即使它是可观察的? - How to get a variable from angularfire, even though it is an observable? 通过 angular 模板中的 id 从 angularfire observable 获取用户不工作 - get user by id in angular template from angularfire observable not working 如何在可观察的 Firebase 变量中分配 SnapshotChanges? - How Can I assign the SnapshotChanges in a Observable Firebase Variable? 如何在 Angular 中获取 Firestore collectionGroup 数据作为 Observable? - How to get Firestore collectionGroup datas as an Observable in Angular? 在空集合上使用 firestore/angularfire collectionChanges() 时有没有办法获得初始事件 - Is there a way to get an initial event when using firestore/angularfire collectionChanges() on an empty collection 反转 angularfire2 中的可观察数组 angular 6 - reverse an observable array in angularfire2 angular 6 Firestore,检查在 valueChanges() 期间更改了哪些字段 - Firestore, Check which fields has been changed during valueChanges()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM