gpt4 book ai didi

angular - Firestore 事件文档快照监听器中断排序

转载 作者:行者123 更新时间:2023-12-03 23:39:33 30 4
gpt4 key购买 nike

我遇到了一个firestore问题,希望有人可以帮助我。
我有一个事件的文档快照监听器,它似乎正在破坏排序行为,我不知道为什么。
在我的组件的构造函数中,我初始化了一次文档快照监听器:

this.listen = this.fs.collection('users').doc('0EwcWqMVp9j0PtNXFDyO').ref.onSnapshot(t => {
console.log(t)
})
每当我单击“排序”按钮时,它都会初始化一个按名字排序的新集合查询。
  async onSort() {
if (this.first) {
this.first();
}

this.sort = this.sort === 'asc'? 'desc' : 'asc';
alert(this.sort)
let arr = []
let lastDoc = null
let queryRef = this.fs.firestore.collection('users').orderBy('firstName', this.sort as any).limit(20);
this.users$ = this._users$.asObservable()

// initialize a blank list
this._users$.next([])

// subscribe to user list snapshot changes
const users1: { users: any, last: any } = await new Promise((resolve, reject) => {
this.first = queryRef.onSnapshot((doc) => {
console.log("Current data: ", doc);

const users = doc.docs.map(t => {
return {
id: t.id,
...t.data() as any
}
})
console.log(users)
resolve({
users: users,
last: doc.docs[doc.docs.length -1]
})
});

})
this._users$.next(this._users$.value.concat(users1.users))

}
但是,这并没有按预期工作。排序返回一条记录(应该有 20 条记录,基于限制)。
enter image description here
有趣的是,取消订阅文档快照会修复排序问题。正在返回 20 条记录,并且排序行为正确。
enter image description here
有人可以解释我做错了什么吗?
这是重现该问题的最小 Stackblitz。
Demo of Issue
[编辑]
越来越接近解决方案和理解......
感谢@ZackReam 的解释以及@Robin 和@Zack 的规范答案。
看来 this._firestore.firestore.collection('users').orderBy('firstName', this.sort as any).limit(20).onSnapshot(...)确实发出了两次 - 一次用于事件文档监听器(在缓存中有 1 条记录),第二次用于排序集合(因为 switchMap 不在缓存中,因为每次执行 sort 时都会取消订阅)。
我们可以在 Zack 发布的功能演示中看到这一点——它闪烁着与文档监听器相对应的一条记录,然后在片刻之后,列表中填充了排序后的集合。
你的听众越活跃,结果的闪现就越奇怪。这是设计使然吗?对我来说似乎有缺陷......
直觉上,我希望 snapshotChanges()valueChanges()来自 this._firestore.firestore.collection('users').orderBy('firstName', this.sort as any).limit(20)查询返回 20 个结果(排序后的前 20 个),独立于任何其他文档监听器。这个查询的第一个快照是文档查询的初始事件文档,这与直觉相反——这应该与排序查询无关。

最佳答案

我在一个简化的环境中使用了您的示例数据,我想我知道发生了什么。
Here is my playground ,只需更新 AppModule指向您的 Firebase 项目。
发生了什么?
当您调用 onSort() ,您正在重新订阅 queryRef.onSnapshot .此回调触发两次:

  • 订阅后,它会立即触发 Firestore 本地缓存中可用的一组初始数据(在您的情况下,它有一个记录,我稍后会解释)。
  • 获取实际数据后,它会使用您希望的完整数据集再次触发。

  • In the playground, make sure Document is subscribed, then subscribe to the Sorted Collection. In the console, you'll see both times it fires:

    enter image description here


    不幸的是,由于您将此监听器包装在 Promise 中,因此您只能获得第一次触发,因此只能获得缓存中的单个记录。
    为什么取消订阅文档快照会修复它?
    似乎本地缓存是根据对 onSnapshot 的订阅来填充的。目前是开放的。因此,在您的情况下,您有一个监听器来监听单个记录的快照,因此这是您的缓存中唯一的东西。

    In the playground, try hitting Log Cache with various subscription states.For instance, while only Document Subscribed is true, the cache only has the one record.While both subscriptions are active, you'll see around 20 records in the cache.

    If you unsubscribe from everything and hit Log Cache, the cache is empty.


    事实证明,如果在上面的步骤 1 中没有数据可以从缓存中返回,它会完全跳过该步骤。

    In the playground, make sure Document is UNsubscribed, then subscribe to the Sorted Collection. In the console, you'll see it fired only once:

    enter image description here


    这恰好适用于您的 Promise,因为第一次也是唯一一次触发包含您希望的数据。
    如何解决这个问题?
    This comment in the firebase-js-sdk repo按预期描述了这种行为,以及原因。
    Promise 与 .onSnapshot 配对是打乱数据流的主要因素,因为 .onSnapshot预计会不止一次开火。你可以切换到 .get相反,它在技术上会起作用。
    然而,正如 Robin 指出的那样,专注于利用 @angular/fire functionality 的更具 react 性的 RxJS 方法。 ) 会有很长的路要走。
    Fully-functional example.

    关于angular - Firestore 事件文档快照监听器中断排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66553754/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com