更新记录

v1.0.0(2023-12-04)

2023-12-04: 核心方案案例完成


平台兼容性

Vue2 Vue3
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
HBuilderX 3.6.0 app-vue app-nvue
钉钉小程序 快手小程序 飞书小程序 京东小程序
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari

批量请求案例(百条!)解决方案

  • 通过Promise实现分批请求,并做好控制
    • 离开页面时,取消未完成的请求任务,返回页面后,检测有无需要继续的任务,若有则继续执行剩余任务
    • 每项请求均可自定义请求参数

核心代码:

  • BatchHttp.js
    
    // 注:这里的 httpRequest 请根据自己项目而定,比如我的项目是uniapp,里面的http请求是 uni.request,若你的项目是 axios 或者 ajax,那就根据它们来对 BatchHttp 中的某些部分
    import httpRequest from './httpRequest.js'

/**

  • 批量请求封装 */ export class BatchHttp {

    /**

    • 构造函数
    • @param {Object} http - http请求对象(该http请求拦截器里切勿带有任何有关ui的功能,比如加载对话框、弹窗提示框之类),用于发起请求,该http请求对象必须满足:返回一个包含取消请求函数的对象,因为在 this.cancelAll() 函数中会使用到 */ constructor(http=httpRequest) { / @private @type {Object[]} 请求任务数组 */ this.resTasks = [] /* @private @type {Object} uni.request对象 / this.http = http / @private @type {boolean} 取消请求标志 */ this.canceled = false }

    /**

    • 将数组拆分成多个 size 长度的小数组
    • 常用于批量处理控制并发等场景
    • @param {Array} array - 需要拆分的数组
    • @param {number} size - 每个小数组的长度
    • @returns {Array} - 拆分后的小数组组成的二维数组 */

      chunk(array, size) {

      const chunks = [] let index = 0

      while(index < array.length) { chunks.push(array.slice(index, size + index)) index += size; }

      return chunks }

    /**

    • 单个数据项请求
    • @private
    • @param {Object} reqOptions - 请求配置
    • @param {Array<string[]>} reqItemKeys - 请求时需要从 items 的每一项中获取数据的 key,这是个二维数组,reqItemKeys[i][0] 是请求接口参数key,reqItemKeys[i][1]是从 items 每一项中获取值的key
    • @param {Object} item - 数据项
    • @returns {Promise} 请求Promise */

      singleRequest(reqOptions, reqItemKeys, item) {

      return new Promise((resolve, _reject) => { const options = { url: reqOptions.url, method: reqOptions.method || 'GET', // data: reqOptions.data, success: res => { resolve({sourceItem:item, res}) } } let query = reqOptions.data || {} // 若设置了 reqItemKeys ,则根据此参数设置请求参数 if (Array.isArray(reqItemKeys) && reqItemKeys.length>0) { reqItemKeys.forEach(keyAry => { query[keyAry[0]] = item[keyAry[1]] }) } options.data = query const task = this.http(options) this.resTasks.push(task) }) }

    /**

    • 批量请求控制
    • @private
    • @async
    • @param {Object} options - 函数参数项
    • @param {Array} options.items - 数据项数组
    • @param {Object} options.reqOptions - 请求配置
    • @param {Array<string[]>} options.reqItemKeys - 请求时需要从 items 的每一项中获取数据的 key,这是个二维数组,reqItemKeys[i][0] 是请求接口参数key,reqItemKeys[i][1]是从 items 每一项中获取值的key
    • @param {number} [options.concurrentNum=10] - 并发数
    • @param {Function} [options.chunkCallback] - 分块回调
    • @returns {Promise} */ async #batchRequest({items, reqOptions, reqItemKeys=[], concurrentNum = 10, chunkCallback=(ress)=>{}}) { const promiseArray = [] let data = [] const passFlagProp = this.passFlagProp if(!passFlagProp) { data = items } else { // 若设置独立 passFlagProp 值,则筛选出对应属性值为空的数据(避免每次都重复请求所有数据,实现“继续未完成的批量请求任务”) data = items.filter(d => !Object.hasOwnProperty.call(d, passFlagProp) || !d[passFlagProp]) } // -- if(data.length === 0) return

      data.forEach(item => { const requestPromise = this.#singleRequest(reqOptions, reqItemKeys, item) promiseArray.push(requestPromise) })

      const promiseChunks = this.#chunk(promiseArray, concurrentNum) // 切分成 n 个请求为一组

      for (let ck of promiseChunks) { // 若当前处于取消请求状态,则直接跳出 if(this.canceled) break // 发起一组请求 const ckRess = await Promise.all(ck) // 控制并发数 chunkCallback(ckRess) // 每完成组请求,都进行回调 } }

    /**

    • 设置用于识别忽略数据项的字段名
    • (借此参数可实现“继续上一次完成的批量请求”);
    • 如:passFlagProp='url' 时,在执行 exec 时,会过滤掉 items['url'] 不为空的数据,借此可以实现“继续上一次完成的批量请求”,避免每次都重复所有请求
    • @param {string} val */ setPassFlagProp(val) { this.passFlagProp = val }

    /**

    • 执行批量请求操作
    • @param {Object} options - 函数参数项
    • @param {Array} options.items - 数据项数组
    • @param {Object} options.reqOptions - 请求配置
    • @param {Array<string[]>} options.reqItemKeys - 请求时需要从 items 的每一项中获取数据的 key,这是个二维数组,reqItemKeys[i][0] 是请求接口参数key,reqItemKeys[i][1]是从 items 每一项中获取值的key
    • @param {number} [options.concurrentNum=10] - 并发数
    • @param {Function} [options.chunkCallback] - 分块回调 */ exec(options) { this.canceled = false this.#batchRequest(options) }

    /**

    • 取消所有请求任务 */ cancelAll() { this.canceled = true for(const task of this.resTasks) { task.abort() } this.resTasks = [] } }

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问