背景
手机APP业务中数据查询大多为滚动触底加载更多数据,如果使用传统的分页查询当遇到以下场景时就会出现数据错误:
例如某个APP页面数据展示按添加时间降序排序,默认每次请求十条数据
当用户A查询第一页数据(数据1-10)后,用户B添加了一条新数据,此时用户A操作触发加载更多数据,此时请求第二页数据,由于用户B新增了一条数据N1,按照数据按降序排列 则会把用户A查到第一页的最后一条数据10后推到第二页,此时A请求的第二页数据则会再次出现之前已经出现过的数据10,页面就会重复渲染数据10.这样的结果显示不是用户需要的。
为了解决该问题,所以采用迭代器来执行查询操作
构造迭代器
在 类中增加生成迭代器函数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) }}复制代码