【使用Promise处理多个重复请求】

如何使用Promise优雅的处理多个重复请求

面对各种各样,千奇百怪,层出不穷的业务需求,解决方式也是各有千秋,各领风骚数百年🤧;
至于什么方式最好,不要听别人的看法,切记:“没有最好的,只有最合适的。。。
所以记录分享一下个人感觉较好的处理重复请求的方法,不喜勿喷,切勿当真🤏

分析对比

相比对于处理重复请求的方式大家都知道很多(不排除这种👇),常见的可以分为在response返回之前发现重复请求就return掉,或者使用 节流/防抖 来间接规避用户频繁操作两种。
最近在学习工作过程中,发现这两个方法并不适合所有需求。。。

问题描述

在面对多次重复请求时,如何使用一种更加人性化的方式去判断请求是否为无效请求?
在网上看了一些大佬的处理方案后,感觉分析的相对通俗易懂地就这个了👇
在这里插入图片描述
是不是把你手里的牌猜的一清二楚🤐

解决方案

直接上干货,多说不宜必自毙,且行且珍惜

核心思想

  1. 初始化一个handleList的数组;
  2. 在请求发送前,根据入参是否相同判断是否为重复请求
    注意:
    非重复请求:把改请求的参数和请求返回的Promise添加至数组中,
    重复请求:使用find查找直接返回对应的Promise;
  3. 请求完成后把handleList中之前添加的请求信息移除。

总之这个方案可以说是万能模板,无论是使用axios、jq、fetch、小程序request。

代码示例

接下来是核心代码,按需引入

let handleList = [] // 请求列表
/**
 * 模拟请求
 * @author waldon
 * @date 2021-05-22
 */
const httpRequest = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve(`请求成功,时间戳为:${new Date().getTime()}`)
    }, 1000)
  })
}
/**
 * 请求的相关处理
 * @author waldon
 * @date 2020/6/9
 * @param {String} url -
 * @param {Object} requestObj - 请求参数
 * @returns {Promise} - 请求的promise
 */
function requestTest(url, requestObj = {}) {
  // 因为入参一般不会涉及到复杂类型,JSON.stringify进行序列化对比其实够用了
  // 有个局限性就是入参的顺序改变了就会影响判断,不过这种特殊的改变一般在重复请求中不会出现
  // 实在是有这种需求的,换成其他递归对比的api,lodash也有类似的api
  const sameHandle = handleList.find(
    (item) => item.url === url && JSON.stringify(item.requestObj) === JSON.stringify(requestObj)
  )
  if (sameHandle) {
    // 遇到相同请求直接返回之前请求的promise
    console.log(`存在重复请求,直接返回`)
    return sameHandle.handle
  }
  const handle = new Promise((resolve, reject) => {
    httpRequest()
      .then((res) => {
        resolve(res)
      })
      .catch((err) => {
        reject(err)
      })
      .finally(() => {
        // 无论请求结果如果,都需要把对应的请求移除掉
        handleList = handleList.filter((item) => item.url !== url)
      })
  })
  handleList.push({ url, requestObj, handle })
  return handle
}

// *******************************我是华丽的分割线 开始使用*******************************
const params = {
  name: 'waldon'
}
requestTest('/ajax/sameUrl', params).then((res) => {
  console.log(`首次请求结果`, res)
  console.log(`handleList:`, handleList)
})
requestTest('/ajax/sameUrl', params).then((res) => {
  console.log(`重复请求结果`, res)
  console.log(`handleList:`, handleList) // 请求列表中始终只有一个请求
  setTimeout(() => {
    console.log(`请求完成后的handleList:`, handleList) // 请求完成handleList对应的请求会被清除
  }, 100)
})
setTimeout(() => {
  // 特意延迟500ms请求,因为我们设置了接口1s才返回,所以应该得到一样的结果
  requestTest('/ajax/sameUrl', params).then((res) => {
    console.log(`重复请求结果`, res)
    console.log(`handleList:`, handleList)
  })
}, 500)

输出结果

存在重复请求,直接返回
存在重复请求,直接返回
首次请求结果 请求成功,时间戳为:1621650375540
handleList: [
  {
    url: '/ajax/sameUrl',
    requestObj: { name: 'waldon' },
    handle: Promise { '请求成功,时间戳为:1621650375540' }
  }
]
重复请求结果 请求成功,时间戳为:1621650375540
handleList: [
  {
    url: '/ajax/sameUrl',
    requestObj: { name: 'waldon' },
    handle: Promise { '请求成功,时间戳为:1621650375540' }
  }
]
重复请求结果 请求成功,时间戳为:1621650375540
handleList: [
  {
    url: '/ajax/sameUrl',
    requestObj: { name: 'waldon' },
    handle: Promise { '请求成功,时间戳为:1621650375540' }
  }
]
请求完成后的handleList: []

注意点

不要对response中的数据进行增删操作。因为重复请求返回Promise中的对象引用地址都是同一个,改动了就会造成数据污染。特殊情况时可以浅拷贝响应结果再处理,或者是增加对应的断言。
处理重复的请求时,最好在log中提示一下,同时在组件中注释好原因和使用场景,避免他人误改
做好极端情况下,请求失败的处理,设置有效时间置空和移除请求信息,避免因为闭包堆积过多无用的请求信息造成内存泄漏。

不知道有没有解救你于水火,但我看完感觉是很不错,虽然不懂为什么好,好在哪,但起码感觉是对的(悟性不够🤪),跟着感觉走。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值