背景
手机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)
}
}
复制代码