背景
手機APP業務中資料查詢大多為滾動觸底載入更多資料,如果使用傳統的分頁查詢當遇到以下場景時就會出現資料錯誤:
例如某個APP頁面資料展示按新增時間降序排序,預設每次請求十條資料
當使用者A查詢第一頁資料(資料1-10)後,使用者B新增了一條新資料,此時使用者A操作觸發載入更多資料,此時請求第二頁資料,由於使用者B新增了一條資料N1,按照資料按降序排列 則會把使用者A查到第一頁的最後一條資料10後推到第二頁,此時A請求的第二頁資料則會再次出現之前已經出現過的資料10,頁面就會重複渲染資料10.這樣的結果顯示不是使用者需要的。
為了解決該問題,所以採用迭代器來執行查詢操作
構造迭代器
在 LeancloudHelp 類中增加生成迭代器函式createIterator
total為要查詢資料的總條數,在第一次查詢後得到具體的總記錄數
/**
* 迭代查詢
* @param {*} objName 物件名
* @param {*} params 查詢引數列表 約定迭代查詢需要的引數(日期型別)放在第一位
* @param {*} sorts 排序列表 只支援單個日期型別欄位排序
* @param {*} limit 每次查詢數量
*/
static createIterator(objName, params, sorts, limit = 10) {
let total = limit
let i = 0
return {
next: async (lastCreatedAt) => {
const done = (i >= total)
let data
if (params) {
params[0].value = new Date(lastCreatedAt)
}
await LeancloudHelp.getList(objName, params, limit, 1, sorts, i === 0).then((res) => {
data = res.data
if (i === 0) {
total = res.total
}
}).catch((error) => {
throw error
})
i += limit
const value = done ? undefined : data
return {
done,
value,
}
},
}
}
複製程式碼
迭代器呼叫
query 為頁面查詢方法, createIterator為要實現迭代查詢的類在這裡構造相關的查詢引數和排序方式
首次呼叫query方法時要先建立迭代器物件,然後預設執行一次迭代查詢。
query = () => {
console.log('iterator', this.state.iterator)
if (!this.state.iterator) {
const iterator = Notice.createIterator()
this.setState({iterator}, () => {
console.log('iterator', this.state.iterator)
this.state.iterator.next(new Date()).then((res) => {
console.log(res)
if (!res.done) {
if (res.value.length) {
this.setState({lastCreatedAt: res.value[res.value.length - 1].createdAt})
}
}
}).catch((error) => {
console.error(error)
})
})
} else {
this.state.iterator.next(this.state.lastCreatedAt).then((res) => {
console.log(res)
if (!res.done) {
if (res.value.length) {
this.setState({lastCreatedAt: res.value[res.value.length - 1].createdAt})
}
}
}).catch((error) => {
console.error(error)
})
}
}
static createIterator(title) {
const params = [
{colName: 'createdAt', value: undefined, queryType: Enum.queryType.lessThan},
{colName: 'title', value: title, queryType: Enum.queryType.contains},
]
const sorts = [
{sortWay: Enum.sortWay.descending, colName: 'createdAt'},
]
const limit = 10
return LeancloudHelp.createIterator('Notice', params, sorts, limit)
}
}
複製程式碼