Firebase 延迟加载
Firebase lazy load
我正在尝试延迟加载 firebase 项目,以便稍后在用户到达 div 容器末尾时加载更多项目。当我删除 .endAt()
和 .startAt()
时,我收到了 15 个项目,尽管它们没有增加并且卡在这 15 个项目上。
当我保持 .endAt()
和 .startAt()
时,我收到了 firebase 警告
Using an unspecified index. Consider adding ".indexOn": "title" at /items
即使设置了 .indexOn
。我对那个警告感到困惑。在此先感谢您的帮助。
Firebase 结构
{
"items" : {
"-Kk6aHXIyR15XiYh65Ht" : {
"author" : "joe",
"title" : "Product 1"
},
"-Kk6aMQlh6_E3CJt_Pnq" : {
"author" : "joe",
"title" : "Product 2"
}
},
"users" : {
"RG9JSm8cUndpjMfZiN6c657DMIt2" : {
"items" : {
"-Kk6aHZs5xyOWM2fHiPV" : "-Kk6aHXIyR15XiYh65Ht",
"-Kk6aMTJiLSF-RB3CZ-2" : "-Kk6aMQkw5bLQst81ft7"
},
"uid" : "RG9JSm8cUndpjMfZiN6c657DMIt2",
"username" : "joe"
}
}
}
安全规则
{
"rules": {
".read": true,
".write": "auth != null",
"users":{
"$uid": {
".write": "$uid === auth.uid"
"items":{
".indexOn": "title",
"$itemId": {
"title": {".validate": "...}
"type": {".validate": "...}
}
}
}
}
}
}
}
延迟加载的代码结构
let _start = 0,
_end = 14,
_n = 15;
function lazyLoadItems(){
firebase.database().ref('items')
.orderByChild('title')
.startAt(_start)
.endAt(_end)
.limitToFirst(_n)
.on("child_added", snapshot=> console.log(snapshot.val()));
_start += _n;
_end += _n;
}
您误解了 Firebase 查询的工作原理。如果使用 hard-coded 值最容易查看:
firebase.database().ref('items')
.orderByChild('title')
.startAt(0)
.endAt(14)
.limitToFirst(15)
没有包含 title=0
或 title=14
的项目,因此查询不匹配任何内容。
Firebase 数据库查询匹配您订购的 属性 的值。因此,当您按 title
排序时,您在 startAt
和 endAt
中指定的值必须是标题。例如
ref.child('items')
.orderByChild('title')
.startAt("Product 1")
.endAt("Product 1")
.limitToFirst(15)
.on("child_added", function(snapshot) { console.log(snapshot.val()); });
请参阅此工作示例:http://jsbin.com/hamezu/edit?js,console
要实现分页,您必须记住上一页的最后一项并将其传递给下一个调用:startAt(titleOfLastItemOnPreviousPage, keyOfLastItemOnPreviousPage)
.
startAfter 是最后一个元素
每次你必须发送最后一个元素:
const lastAlert = querySnapshot.docs[querySnapshot.docs.length - 1]
这里有一个例子:
export const fetchAlerts = (createdForId, startAfter) => {
return new Promise((resolve, reject) => {
firebase
let query = firebase
.firestore()
.collection('alerts')
.where('generated_for.uid', '==', createdForId)
.where('read', '==', false)
.orderBy('created_at', 'desc')
.limit(25)
if (startAfter) {
query = query.startAfter(startAfter)
}
query
.get()
.then(querySnapshot => {
const lastAlert = querySnapshot.docs[querySnapshot.docs.length - 1]
const alerts = querySnapshot.docs.map(doc => ({
...doc.data(),
uid: doc.id,
}))
resolve(alerts)
resolve({ alerts, lastAlert })
})
.catch(error => {
console.log(error.message)
我正在尝试延迟加载 firebase 项目,以便稍后在用户到达 div 容器末尾时加载更多项目。当我删除 .endAt()
和 .startAt()
时,我收到了 15 个项目,尽管它们没有增加并且卡在这 15 个项目上。
当我保持 .endAt()
和 .startAt()
时,我收到了 firebase 警告
Using an unspecified index. Consider adding ".indexOn": "title" at /items
即使设置了 .indexOn
。我对那个警告感到困惑。在此先感谢您的帮助。
Firebase 结构
{
"items" : {
"-Kk6aHXIyR15XiYh65Ht" : {
"author" : "joe",
"title" : "Product 1"
},
"-Kk6aMQlh6_E3CJt_Pnq" : {
"author" : "joe",
"title" : "Product 2"
}
},
"users" : {
"RG9JSm8cUndpjMfZiN6c657DMIt2" : {
"items" : {
"-Kk6aHZs5xyOWM2fHiPV" : "-Kk6aHXIyR15XiYh65Ht",
"-Kk6aMTJiLSF-RB3CZ-2" : "-Kk6aMQkw5bLQst81ft7"
},
"uid" : "RG9JSm8cUndpjMfZiN6c657DMIt2",
"username" : "joe"
}
}
}
安全规则
{
"rules": {
".read": true,
".write": "auth != null",
"users":{
"$uid": {
".write": "$uid === auth.uid"
"items":{
".indexOn": "title",
"$itemId": {
"title": {".validate": "...}
"type": {".validate": "...}
}
}
}
}
}
}
}
延迟加载的代码结构
let _start = 0,
_end = 14,
_n = 15;
function lazyLoadItems(){
firebase.database().ref('items')
.orderByChild('title')
.startAt(_start)
.endAt(_end)
.limitToFirst(_n)
.on("child_added", snapshot=> console.log(snapshot.val()));
_start += _n;
_end += _n;
}
您误解了 Firebase 查询的工作原理。如果使用 hard-coded 值最容易查看:
firebase.database().ref('items')
.orderByChild('title')
.startAt(0)
.endAt(14)
.limitToFirst(15)
没有包含 title=0
或 title=14
的项目,因此查询不匹配任何内容。
Firebase 数据库查询匹配您订购的 属性 的值。因此,当您按 title
排序时,您在 startAt
和 endAt
中指定的值必须是标题。例如
ref.child('items')
.orderByChild('title')
.startAt("Product 1")
.endAt("Product 1")
.limitToFirst(15)
.on("child_added", function(snapshot) { console.log(snapshot.val()); });
请参阅此工作示例:http://jsbin.com/hamezu/edit?js,console
要实现分页,您必须记住上一页的最后一项并将其传递给下一个调用:startAt(titleOfLastItemOnPreviousPage, keyOfLastItemOnPreviousPage)
.
startAfter 是最后一个元素
每次你必须发送最后一个元素:
const lastAlert = querySnapshot.docs[querySnapshot.docs.length - 1]
这里有一个例子:
export const fetchAlerts = (createdForId, startAfter) => {
return new Promise((resolve, reject) => {
firebase
let query = firebase
.firestore()
.collection('alerts')
.where('generated_for.uid', '==', createdForId)
.where('read', '==', false)
.orderBy('created_at', 'desc')
.limit(25)
if (startAfter) {
query = query.startAfter(startAfter)
}
query
.get()
.then(querySnapshot => {
const lastAlert = querySnapshot.docs[querySnapshot.docs.length - 1]
const alerts = querySnapshot.docs.map(doc => ({
...doc.data(),
uid: doc.id,
}))
resolve(alerts)
resolve({ alerts, lastAlert })
})
.catch(error => {
console.log(error.message)