Firestore .startAt 无法正常工作
Posted
技术标签:
【中文标题】Firestore .startAt 无法正常工作【英文标题】:Firestore .startAt is not working properly 【发布时间】:2019-03-13 10:46:03 【问题描述】:infiniteHandler($state)
var next = db
.collection("posts")
.orderBy("timestamp", "desc")
.startAfter(this.lastVisible)
.limit(3)
next.get().then(documentSnapshots =>
//Get the last visible document
// this.lastVisible =
// documentSnapshots.docs[documentSnapshots.docs.length - 1]
if (documentSnapshots.docs.length == 0) $state.complete()
else
this.$store.commit(
"modules/posts/updateLastVisible",
documentSnapshots.docs[documentSnapshots.docs.length - 1].data()
.timestamp
)
documentSnapshots.forEach(doc =>
var post = doc.data()
post.docID = doc.id
this.$store.commit("modules/posts/pushPost", post)
)
$state.loaded()
)
这是我的无限加载处理程序,一旦到达列表末尾,它就会获取新的数据库条目。到目前为止工作正常。
这是我在页面加载时的第一次抓取
async fetch( store )
if (store.state.modules.posts.posts.length < 5)
let posts = []
await db
.collection("posts")
.orderBy("timestamp", "desc")
.limit(3)
.get()
.then(querySnapshot =>
store.commit(
"modules/posts/updateLastVisible",
querySnapshot.docs[2].data().timestamp
)
querySnapshot.forEach(doc =>
var x = doc.data()
x.docID = doc.id
posts.push(x)
)
)
store.commit("modules/posts/fetchedPosts", posts)
基本上,问题是当我在无限加载处理程序中获取时,我在页面加载时再次获取前 3 个条目,这导致条目显示两次,这不应该发生,因为 this.lastVisible
有我在加载时获取的第三个元素的时间戳,所以应该忽略这些。
在这些元素之后,.startAfter
一切正常,但前 3 个再次加载没有意义。
我用 devtools 检查了商店,一切正常,this.lastVisible
在第一次调用无限加载处理程序时具有正确的值。
赏金编辑: 好的,所以我仍然有这个问题,我尝试更多地解决它以找到问题,但它仍然在发生......我现在将设置一个赏金,我希望任何人都能够提供帮助。
【问题讨论】:
我感觉这与在 this.lastVisible 设置之前运行的infiniteHandler() 有关。尝试在函数顶部记录 lastVisible。 @SeanRussell 抱歉,回复晚了,是的,它确实第一次记录了一个无效的对象,这导致它基本上从整个列表的入口点开始,但我怎么能改变这种行为? 在 infaniteHandler() 中进行初始调用,它似乎在您第一次异步 fetch() 后工作 @SeanRussell 但在提取完成之前无限处理程序不应该能够工作吗? 我的意思是调整您的逻辑/代码以在一个功能中执行操作。你说除了前三个文件被复制之外它还有效。好吧,废弃调用前三个文档的函数。 【参考方案1】:您实际上并不需要第一次提取。挂载时将自行调用infiniteHandler。如果它没有调用,那么您可以尝试使用该函数
this.$refs.infiniteLoading.attemptLoad(); // 'infiniteLoading' 是组件的 ref 属性
这实际上会为你调用infiniteHandler函数。
编辑:检查其中一个功能是否正在运行。在处理程序部分
infiniteHandler($state)
//Check if its currently loading
this.$nextTick(()=>
if (this.isDocSnapShotLoading)
return;
);
//set as currently loading
this.isDocSnapShotLoading = true;
var next = db
.collection("posts")
.orderBy("timestamp", "desc")
.startAfter(this.lastVisible)
.limit(3)
next.get().then(documentSnapshots =>
//Get the last visible document
// this.lastVisible =
// documentSnapshots.docs[documentSnapshots.docs.length - 1]
if (documentSnapshots.docs.length == 0) $state.complete()
else
this.$store.commit(
"modules/posts/updateLastVisible",
documentSnapshots.docs[documentSnapshots.docs.length - 1].data()
.timestamp
)
documentSnapshots.forEach(doc =>
var post = doc.data()
post.docID = doc.id
this.$store.commit("modules/posts/pushPost", post)
)
$state.loaded()
//set completed loading
this.isDocSnapShotLoading = false;
)
在获取部分
async fetch( store )
if (store.state.modules.posts.posts.length < 5)
//check if currently loading
this.$nextTick(()=>
if (this.isDocSnapShotLoading)
return;
);
//set as currently loading
this.isDocSnapShotLoading = true;
let posts = []
await db
.collection("posts")
.orderBy("timestamp", "desc")
.limit(3)
.get()
.then(querySnapshot =>
store.commit(
"modules/posts/updateLastVisible",
querySnapshot.docs[2].data().timestamp
)
querySnapshot.forEach(doc =>
var x = doc.data()
x.docID = doc.id
posts.push(x)
)
//set as completed loading.
this.isDocSnapShotLoading = false;
)
store.commit("modules/posts/fetchedPosts", posts)
【讨论】:
但是如果我在infiniteHandler 中使用我的Front Articles 获取逻辑,这是否意味着只有在触发infiniteLoading 时才会获取内容?即使我尝试在页面加载时调用它,我仍然没有 fetch nuxtjs.org/api/pages-fetch 在 s-s-r 和速度方面给我带来的好处 infiniteHandler 应该在您向下滚动以获取更多内容时继续加载其他内容。因此,即使在安装应用程序时调用它,当您向下滚动并且有更多内容时,它也会继续调用。 我不确定 s-s-r 部分,因为您更了解您的应用程序结构和设计,因此我无法就此提供建议。如果 s-s-r 确实对您的应用程序有帮助,那么您可以做的是维护一个商店或组件变量,并在获取工作时将其设置为 true。在infiniteHandler中检查这个变量,如果它是真的,就阻止它加载。 那么 fetch() 正在工作,因为我在首页上的 Big Images 中显示 3 个最新帖子,在此之下我有一个无限的加载列表,所以如果我们谈论同样的事情,那么 fetch 本身工作得很好很好,商店也填充了我传递给startAfter()
的正确值,所以我很难通过值检查等来做一个简单的解决方法。
上面的帖子已经在上面进行了编辑以添加检查。如果函数在同一个组件中,您可以使用组件变量。否则,您可能需要将其添加为商店状态。【参考方案2】:
好的,所以我找到了一个暂时的解决方案,它现在可以工作但仍然不漂亮:
documentSnapshots.forEach(doc =>
if (
doc.id !== this.posts[0].docID &&
doc.id !== this.posts[1].docID &&
doc.id !== this.posts[2].docID
)
var post = doc.data()
post.docID = doc.id
this.$store.commit("modules/posts/pushPost", post)
)
我也尝试通过不同的解决方案来提高效率,感谢您的帮助。
【讨论】:
【参考方案3】:如果您想忽略infiniteHandler 中的前3 个帖子,您可以创建一个帖子数组来存储帖子ID 并检查帖子ID 是否已经加载。我知道这应该使用查询来解决,但作为临时解决方案,我希望它对你有用。
infiniteHandler($state)
var next = db
.collection("posts")
.orderBy("timestamp", "desc")
.startAfter(this.lastVisible)
.limit(3)
next.get().then(documentSnapshots =>
//Get the last visible document
// this.lastVisible =
// documentSnapshots.docs[documentSnapshots.docs.length - 1]
if (documentSnapshots.docs.length == 0) $state.complete()
else
this.$store.commit(
"modules/posts/updateLastVisible",
documentSnapshots.docs[documentSnapshots.docs.length - 1].data()
.timestamp
)
documentSnapshots.forEach(doc =>
var check = this.postIdArray.indexOf(doc.id);
if(check == -1)
var post = doc.data()
post.docID = doc.id
this.$store.commit("modules/posts/pushPost", post);
this.postIdArray[] = doc.id;
)
$state.loaded()
)
async fetch( store )
this.postIdArray = [];
if (store.state.modules.posts.posts.length < 5)
let posts = []
await db
.collection("posts")
.orderBy("timestamp", "desc")
.limit(3)
.get()
.then(querySnapshot =>
store.commit(
"modules/posts/updateLastVisible",
querySnapshot.docs[2].data().timestamp
)
querySnapshot.forEach(doc =>
var x = doc.data()
x.docID = doc.id
this.postIdArray[] = doc.id;
posts.push(x)
)
)
store.commit("modules/posts/fetchedPosts", posts)
【讨论】:
谢谢你的想法,但我想在没有类似的东西的情况下开始它,但如果没有其他帮助,那么我可能需要这样的东西...... 您是否检查过您的 this.lastVisible 是否正在更新并在其中获取正确的值? 是的,我通过无限加载器中的 console.log 和 vuex devtools 做到了这一点,我所看到的是,当我在无限加载中记录next
变量时,它第一次看起来不同与其他时间相比调用,而将相同的值传递给它...
你确定infiniteHandler只在用户被读取到页面结束并且第一次调用完成后调用,根据我的理解,第一次发生的事情没有任何内容,所以直接infiniteHandler和第一次调用正在同时调用,因此第一次和问题解决后数据相同。
很遗憾我不在家,所以我现在无法测试,但我会在我回家时检查并再次向您发送消息以上是关于Firestore .startAt 无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章
isEqual to operator 在 Flutter Firestore 中无法正常工作
Firebase firestore onSnapshot 在 useEffect 中无法正常工作