并发合并

136 阅读2分钟

场景:同一个页面多次调取同一个接口,只是传参不一样。以下模拟:获取用户列表,每次传参多个用户ids

思路:

  1. 每次调用封装的api2后,都要返回promise,而resolve是后台返回后执行。此时需要把所传参数和resolve都保存到一个list中,等待后面遍历执行。
  2. 一定时间内,把所有参数合并,只向后台发送一次请求
  3. 后台返回数据后,通过id筛选对应的promise,并resolve返回

代码:

//传参,调用后台接口,返回结果
function getTwoJson(params){
    // console.log(params);
    return fetch('./1.json').then(res=>{
      return res.json()
    })
  }
  
//1、返回promise,resolve等到结果返回再调用,
  //2、把参数和每个resolve保存,
  //3、一定时间内只保留最后一次接口,参数合并, 发送最后一次接口
  //4、返回结果根据id匹配,对应的promise中resolve返回
  //5、清空保存的参数和resolve
function fetchData(apiFun){
    let requestObj = [];
    return function(...args){
        let params = args[0]; 
        let timeout = args[1]; 
        //1、返回promise,resolve等到结果返回再调用,
        return new Promise((resolve,reject)=>{
            //2、把参数和每个resolve保存
            requestObj.push({params,resolve:resolve})
            //前面几次的timer会被清除,永远不会进入setTimeout,也就不会resolve,即promise会一直是pending
            //所以需要保存每个promise的resolve
            requestObj.timer && clearTimeout(requestObj.timer)
            requestObj.timer = setTimeout(()=>{
                //3、一定时间内只保留最后一次接口,参数合并, 发送最后一次接口
                let allParams = getAllParams(requestObj);
                apiFun(allParams).then(res=>{
                    console.log(allParams);
                    //4、返回结果根据id匹配,对应的promise中resolve返回(遍历requestObj)
                    requestObj.map(linkRequest=>{
                        let data = res.filter(d=>linkRequest.params.includes(d.id))
                        linkRequest.resolve(data);
                    })
                    //5、清空保存的参数和resolve
                    requestObj = [];
                })
            },timeout)
        })
    }
}
function getAllParams(obj){
    let arr = [];
    obj.forEach(d=>{
        arr.push(...d.params)
        // arr = arr.concat(d.params)
    })
    let set = new Set(arr);
    return [...set];
}
let getData = fetchData(getTwoJson)
getData([1,2],2000).then(res=>{
    console.log(res);
}).catch(err=>{

})
getData([1,2,3],2000).then(res=>{
    console.log(res);
}).catch(err=>{

})
getData([3,4],2000).then(res=>{
    console.log(res);
}).catch(err=>{

})
setTimeout(()=>{
    getData([3,4],2000).then(res=>{
        console.log(res);
    }).catch(err=>{
    })
},4000)

欢迎大家批评指正