异步并发数限制,异步加法,大数加法,定时器hooks

向下滚动可查看阅读进度

  • 异步并发数限制

    function limit(count, array, iterateFunction) {
      const tasks = []; //保存所有已创建的任务promise
      const tasksDoingNow = []; //保存当前正在执行的任务promise
      let i = 0; //现在执行到第几个元素
      //进入队列
      const enquene = () => {
        //每调用一次,就开始一个新任务
        if (i === array.length) {
          //说明数组里面的任务全都启动过了
          return Promise.resolve(); //返回一个fulfilled,不用再启动了
        }
    
        //启动任务
        const task = Promise.resolve().then(() => {
          return iterateFunction(array[i++]);
          //创建一个已经成功的 Promise,然后进入then,真正执行任务
          //会在微任务队列里面执行而不是立刻执行
          //task就是一个promise
        });
    
        tasks.push(task);
    
        const doingNow = task.then(() => {
          tasksDoingNow.splice(tasksDoingNow.indexOf(doingNow), 1);
        }); //未来等task1成功后,再删除doingNow1
    
        tasksDoingNow.push(doingNow);
        //把doingNow放进去
    
        //控制并发数
        const res =
          tasksDoingNow.length >= count
            ? Promise.race(tasksDoingNow)
            : //race:等待这些任务里任意一个先完成
              //返回一个新的 Promise,这个 Promise 会采用第一个 settled 的 Promise 的状态和值。
              //不管是fulfilled还是rejected
              Promise.resolve(); //不用等,可以马上继续启动下一个任务
        return res.then(enquene);
      };
    
      return enquene().then(() => {
        return Promise.all(tasks);
      });
    }
    
    // test
    const timeout = (i) =>
      new Promise((resolve) => setTimeout(() => resolve(i), i));
    limit(2, [1000, 1000, 1000, 1000], timeout).then((res) => {
      console.log(res); // 输出所有任务的执行结果
    });
  • 异步加法

    function asyncAdd(a, b, callBack) {
      setTimeout(function () {
        callBack(null, a + b);
        // callback(err, res)
        // err:错误信息
        // res:成功结果
      }, 500);
    }
    //调用例如:asyncAdd(1, 2, (err, res) => {console.log(res)})
    
    //1.promise写法
    const promiseAdd = (a, b) => {
      return new Promise((resolve, reject) => {
        asyncAdd(a, b, (err, res) => {
          if (err) {
            reject(err);
          } else {
            resolve(res);
          }
        });
      });
    };
    //2.串行处理返回promise,使用 reduce 函数依次计算所有数的和,返回一个 Promise
    async function serialSum(...args) {
      //async允许函数内部使用await,以及让函数自动返回promise
      //serial,意思是一个接一个执行
      return args.reduce((task, now) => {
        // task:上一次返回的 Promise now:当前这个数字
        return task.then((res) => promiseAdd(res, now));
        //等上一次返回的promise完成
      }, Promise.resolve(0));
      // 创建一个“已经成功”的 Promise,成功结果是 0,此为一开始的task值
      //作为初始的previous value
    }
    
    //3.并行处理:使用 Promise.all 并行计算所有数的和
    //async允许函数内部使用await,以及让函数自动返回promise
    async function parallelSum(...args) {
      if (args.length === 1) {
        return args[0];
      }
      const tasks = []; //存放所有异步加法任务
      for (let i = 0; i < args.length; i = i + 2) {
        tasks.push(promiseAdd(args[i], args[i + 1] || 0));
      }
      const result = await Promise.all(tasks);
      //await 等待 Promise 完成,并取出 Promise 的结果。
      //否则 result 是 Promise,而不是结果数组
      return parallelSum(...result);
    }
  • 大数加法

    const getBigInt = (a, b) => {
      a = a + "";
      b = b + "";
      let i = a.length - 1; //指向个位
      let j = b.length - 1;
      let carry = 0;
      const res = [];
      while (i >= 0 || j >= 0 || carry !== 0) {
        let ivalue = i >= 0 ? Number(a[i]) : 0;
        let jvalue = j >= 0 ? Number(b[j]) : 0;
        let result = ivalue + jvalue + carry;
        carry = Math.floor(result / 10);
        res.push(result % 10);
        i--;
        j--;
      }
      return res.reverse().join("");
    };
  • 定时器hooks

    import { useState, useEffect } from "react";
    const useTimer = (initialSeconds) => {
      const [seconds, setSeconds] = useState(initialSeconds);
      useEffect(() => {
        let intervalId;
        const tick = () => {
          setSeconds((prevSeconds) => prevSeconds - 1);
        };
        if (seconds > 0) {
          intervalId = setInterval(tick, 1000);
          //每隔1000ms执行一次tick
        }
        return () => {
          clearInterval(intervalId);
        }; //返回一个react自己会调用的清理函数,用箭头函数避免他立刻调用
      }, [seconds]);
    
      const resetTimer = (newSeconds) => {
        setSeconds(newSeconds);
      };
      return { seconds, resetTimer };
      //seconds 是为了让组件显示当前剩余时间
      //resetTimer 是为了让组件可以控制定时器,重新设置时间
    };