分组算法实现

需求

有多个calls数组,数组值分类且每个类别至多存放3个,多余的需要用存放在另一个同类数组,且calls表示用户的一组请求,要将用户在短时间内调用的calls,组合成大calls进行请求,并且返回对应的值

注:无法通过key来表示A1 也就是说A1不是唯一的,只能通过index

[A1,B1,C1]//calls
[A2,E1,D1]
[B2,B3,B4]
[B5,C2]

以上分类为
[A1,A2]
[B1,B2,B3]
[B4,B5]
[C1,C2]
[D1]
[E1]

将分类通过批量请求处理,会返回对应的值
[A1,A2]=>[A1_,A2_]
[B1,B2,B3] => [B1_,B2_,B3_]
[B4,B5] => [B4_,B5_] 
[C1,C2] => [C1_,C2_]
[D1] => [D1_]
[E1] => [E1_]

要求将对应值还原为初始的顺序结构
[A1_,B1_,C1_]
[A2_,E1_,D1_]
[B2_,B3_,B4_]
[B5_,C2_]

实现代码

   实现
  // 单个type容器最大量
  const MAX_CALLS = 3
  // debounce延迟
  const DELAY = 100

  // 定义分组id
  let groupId = {
    // 'type': 0
  }
  let callsId = 0
  let callsGroup = {
    // 'groupId_type': {calls,timeOut}
  }
  // 定义分组数据
  const resolveGroup = {
    // callsId: {resolve,calls}
  }

  // 处理分组下的请求是否都拿到了数据,拿到了就返回出去
  function checkedResult(){
    for (let i in resolveGroup) {
      const result = []
      for (let j = 0; j < resolveGroup[i].calls.length; j++) {
        if (!resolveGroup[i].calls[j].result){
          break
        } else {
          result.push(resolveGroup[i].calls[j].result)
        }
      }
      // 每个数据都有结果
      if (result.length === resolveGroup[i].calls.length){
        // 通过开始存储的resolve进行返回
        resolveGroup[i].resolve(result)
        delete resolveGroup[i]
      }
    }
  }

  function request(key){
    const callsData = callsGroup[key].calls
    // 用定时器模拟请求
    setTimeout(()=>{
      // 模拟请求结果
      const result = []
      for (let i = 0;i<callsData.length;i++) {
        result.push(callsData[i].params[0] + '_result')
      }
      // 将请求结果塞到原有的call
      for (let i = 0; i < callsData.length; i++) {
        callsData[i].result = result[i]
      }
      checkedResult()
    }, ~~Math.random()*500)
  }

  // 处理数据
  function handleData(calls){
    // 通过type分组
    for (let i = 0; i < calls.length; i++) {
      if (!groupId[calls[i].type]){
        groupId[calls[i].type] = 0
      }
      const key = `${groupId[calls[i].type]}_${calls[i].type}`
      if (callsGroup[key]) {
        callsGroup[key].calls.push(calls[i])
        // 当前type容器容器满了
        if (callsGroup[key].calls.length >= MAX_CALLS) {
          groupId[calls[i].type] += 1
        }
      } else {
        callsGroup[key] = {
          calls: [calls[i]]
        }
      }
    }
    // 处理calls
    for(let key in callsGroup){
      if (typeof callsGroup[key].timeOut !== 'undefined'){
        clearTimeout(callsGroup[key].timeOut)
      }
      // 满了就发请求
      if (callsGroup[key].calls.length >= MAX_CALLS){
        request(key)
      } else {
        // 未满就设置debounce
        callsGroup[key].timeOut = setTimeout(()=>{
          // debounce到了,没有进来新的calls,执行发请求
          request(key)
        }, DELAY)
      }
    }
  }

  function groupFn(calls){
    return new Promise((resolve => {
      resolveGroup[callsId ++] = {
        resolve,
        calls
      }
      handleData(calls)
    }))
  }

  / 调用
  
  // params为参数,是不固定的,以下按顺序写是为了方便观看结果
  const calls1 = [
    {type: 'a', params: ['a1']},
    {type: 'b', params: ['b1']},
    {type: 'c', params: ['c1']},
  ]
  const calls2 = [
    {type: 'a', params: ['a2']},
    {type: 'e', params: ['e1']},
    {type: 'd', params: ['d1']},
  ]
  const calls3 = [
    {type: 'b', params: ['b2']},
    {type: 'b', params: ['b3']},
    {type: 'b', params: ['b4']},
  ]
  const calls4 = [
    {type: 'b', params: ['b5']},
    {type: 'c', params: ['c2']},
  ]
  groupFn(calls1).then(res =>{
    console.log('calls1 result', res)
  })
  groupFn(calls2).then(res =>{
    console.log('calls2 result', res)
  })
  groupFn(calls3).then(res =>{
    console.log('calls3 result', res)
  })
  groupFn(calls4).then(res =>{
    console.log('calls4 result', res)
  })

以上代码为本人开发新版multicall核心算法,利用分组与对象本身引用特性实现

二次开发multicall中,也使用了类似的分组算法

分组算法逻辑,真的很常用…

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值