关于批量按顺序下载(reduce+promise)

发布时间 2023-11-04 11:33:53作者: 乐盘游

参考文章

promise resolve reject
https://www.cnblogs.com/lunlunshiwo/p/8852984.html#4917337
reduce 按顺序调用
https://juejin.cn/post/7030625338065420302?searchId=202311041036275432B88F9F3A984960AA

注意点

  1. promise结果的使用
  2. reduce中的等待
  3. 结果数组的存储

运行截图

demo

// import React from 'react';
import { Button, Card } from 'antd';

const Test = () =>{
    // 准备回调的次数 模拟待发送的文件数量
const waitForUpdateList = [1,2,3];

let resultList=[]

 function simulateRequest (lastOneValue) {
// 这里传入的index - 1,是为了获取上一轮的返回值
console.log('lastOneValue',lastOneValue);
  const time = 500;
 
  return new Promise(function (resolve, reject) {
    setTimeout(()=>{
          let num = Math.ceil(Math.random() * 10)
    if (num > 5) {
      // 上一轮值存在 且是res 就绑定在这一轮
      const isLastIsRes = lastOneValue&&Object.keys(lastOneValue).includes('success')
      if(isLastIsRes){
        console.log('原本resolve的结果',num);
              resolve({success:num+lastOneValue.success})
      }else{
        resolve({success:num})

      }
    } else {
      reject({error:num})
    }
    },time)

  });
 
 } 
 
 // 循环顺序请求
 
 function cycleRequest () {
 
  console.log('新的一轮开始请求');
 
  // 一个请求周期,这边为了模拟方便长度为 10,实际情况可能是 10000 或 99999 这样的
   const arr = waitForUpdateList
 
  arr.reduce(async (last,_,index) => {
 let lastOneValue ;
   await last;
   if(index){
    lastOneValue = resultList[index-1] 
  }
   return simulateRequest(lastOneValue)
 
    .then((res) => {
 console.log('res',res);
resultList.push(res)

 
    }).catch(e=>{
console.log('e',e)
resultList.push(e)
    }).finally(()=>{
      // 达到边界 显示所有的promise结果
      // 为什么不用useState? 会有延迟 
      if (index + 1 === arr.length) {
        console.log('最终',resultList);

      }
  });
 
  }, undefined)
 
 }
 
 // 启动
 const everyThingDone=()=>{
  console.log('每轮重新开始,清空result');
  resultList=[];
cycleRequest();
}
 
  return <Card
    title="书语"
    bordered={false}
    style={{
      width: 300,
    }}
  >
    
<Button onClick={everyThingDone}>探索链式调用</Button>

  </Card>
}
export default Test;