[英]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.