小程序下滑分页获取数据封装
可能情况:
1、一条数据没有
2、到最后一页
3、请求状态: 正在加载、加载完成、没有更多数据
4、上滑触底,获取数据,应避免重复发送请求,所以使用数据锁
5、防抖和节流:还可以禁用、倒计时、模态等方式防止重复发送请求
思路:
1、判断是否还有数据
2、设置锁,锁开正常获取数据,锁关,证明还在请求数据,后面点击操作不做处理
3、设置一个属性,作为判断是否是最后一页的标识,
4、设置一个获取实时url的属性,因为每次请求的数据的页码都不一样,所以整个url都不一样,需要获取到最新的url
5、发送请求,返回结果为空,返回数据一个空对象,返回结果非空,判断是否是最后一页,并设置最后一页的属性值是true/false
6、如果还有数据,请求的起始条数加上每次获取的条数
7、数据累加
8、释放锁
/** * 分页类不关心细节 * 当用户调用类,请求需要下一页的数据,直接返回数据 * paging 需要保存状态,所以应该要以实例化的形式供调用方调用 */ import {Http} from "./http"; class Paging { start count url //最原始的url 即没有被覆盖的url locker = false req moreData = true //是否有更多数据 accumulator //累加的数据,每次获取新数据要和原来的数据进行累加 // 初始方法 // req 传入的对象,这个对象有可能不止一个url 还带有其他的参数 /** * 初始构造方法 * @param req 传入的对象,这个对象有可能不止一个url 还带有其他的参数 * @param count 每页条数 * @param start 从第几条开始查 */ constructor(req, count, start = 0) { this.start = start this.count = count this.req = req this.url = req.url } /** * 业务调用主方法 * @returns {Promise<{item: *[], moreData: boolean, accumulator: *[], empty: boolean}|{item: *, moreData: *, accumulator: *, empty: boolean}>} */ async getMoreData() { // 检查锁的状态,如果锁是锁住的,证明还有别的请求还没返回,其他的请求将不会进行,当请求返回结果之后,应该释放锁 //判断是否还有数据 if (!this.moreData) { return } // 检查是否已经锁了,也就是请求的数据是否已经返回 if (!this._getLocker()) { return } // 真实请求数据 const data = await this._actualGetData() // 释放锁 this._releaseLocker() return data } /** * 真实发送请求、判断数据结构(异常处理等情况),返回一个对象 * @returns {Promise<null|{item: [], moreData: boolean, accumulator: [], empty: boolean}|{item: *, moreData: *, accumulator: *, empty: boolean}>} * @private */ async _actualGetData() { const req = this._getCurrentReq() let paging = await Http.request(req) if (!paging) { return null } if (paging.total === 0) { return { empty: true, item: [], moreData: false, // 是否为最后一页的标识 accumulator: [] } } this.moreData = this._moreData(paging.total_page, paging.page) // 判断是否还有数据 if (this.moreData) { this.start += this.count } this._accumulate(paging.items) return { empty: false, item: paging.items, moreData: this.moreData, // 是否为最后一页的标识 accumulator: this.accumulator } } /** * 获取当前的对象,也就是当前返回的数据对象 * @returns {*} * @private */ _getCurrentReq() { let url = this.url const params = `start=${this.start}&count=${this.count}` if (url.indexOf('?') !== -1) { // 当访问的地址没有包含其他的参数,如 url= v1/spu/latest + '?' + params url += '&' + params } else { // 当访问的地址包含其他的参数,如 url= v1/spu/latest?other=abc + '&' + params url += '?' + params } this.req.url = url return this.req } /** * 判断是否是最后一页,是否还有数据 * @param totalPage 总页数 * @param pageNum 当前页数,0开始计数 * @returns {boolean} * @private */ _moreData(totalPage, pageNum) { return pageNum < totalPage - 1 } /** * 累加每次请求的数据 * @param items 请求返回的数据 * @private */ _accumulate(items) { this.accumulator = this.accumulator.concat(items) } /** * 获取锁的状态 * @returns {boolean} * @private */ _getLocker() { // 如果锁是锁住的 if (this.locker) { return false } // 如果锁是开的 this.locker = true return true } /** * 释放锁 * @private */ _releaseLocker() { this.locker = false } } export {Paging}