递归调用Promise渲染树

71 阅读1分钟

这是递归调用Promise的案例,用于查询el-tree树形结构。之前是用懒加载做,导致接口只能一层一层的查,每次只返回一层数据,后面需要改成前几层通过接口多次查回来,方便搜索,那么在查的时候需要loading,多次查就要知道什么时候结束,这是第一版案例!

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
  <script>
    function api() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          let arr = [{ name: "1" }, { name: "2" }];
          resolve(arr);
        }, 2000);
      });
    }

    function recursivePromise(i = 0) {
      // 递归的终止条件
      if (i <= 0) {
        return Promise.resolve(i);
      }
      // 返回一个Promise
      return new Promise(async (resolve, reject) => {
        await api();
        console.log(`当前值为 ${i}`);
        resolve(recursivePromise(i - 1)); // 递归调用
      });
    }

    function get(i = 1) {
      console.log(`第${i}轮开始`);
      // 递归的终止条件
      if (i == 2) {
        return Promise.resolve(i);
      }
      i++;
      return new Promise(async (resolve, reject) => {
        const arr = await api();
        // 使用.then获取最后的结果
        recursivePromise(arr.length).then((res) => {
          console.log(`第${i}轮结束`);
          resolve(get(i));
        });
      });
    }

    get().then(() => {
      console.log("终于完了!");
    });
  </script>
</html>

再来一版更符合业务场景

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
  <script>
    // 模拟异步请求,两次返回不一样的数据
    function api() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          let arr = [{ name: "1" }, { name: "2" }];
          resolve(arr);
        }, 2000);
      });
    }
    function api2() {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          let arr = [{ name: "1" }, { name: "2" }, { name: "3" }];
          resolve(arr);
        }, 2000);
      });
    }
    // 递归调用保证一层全部执行完成,把结果给上一层判断是否还要递归
    let narr = [];
    async function recursivePromise(arr, index = 0) {
      if (index < arr.length) {
        let res = await api2();
        narr = [...narr, ...res];
        index++;
        console.log(`请求了 ${index}次`);
        // 在处理完当前元素后,递归调用以处理下一个元素
        return recursivePromise(arr, index);
      } else {
        // 所有元素都已处理完毕,返回一个 resolved Promise 给上级
        return Promise.resolve(narr);
      }
    }
    // 确定递归几层 i是要循环几层 这里i=2,因为模拟两层
    function get(dataArr, i = 0) {
      // 递归的终止条件
      if ( i == 2) {
        return Promise.resolve(i);
      }
      return new Promise(async (resolve, reject) => {  
        i++;
        console.log(`第${i}轮开始`);
        console.log(`第${i}轮有${dataArr.length}条数据`);
        recursivePromise(dataArr).then((res) => {
          console.log(`第${i}轮结束`);
          console.log(`第${i}轮共返回了${res.length}条数据`);
          resolve(get(res, i));
        });
      });
    }
    // 确定所以函数执行完
    async function init() {
      // 初始化查一次

      const arr = await api();
      get(arr).then(() => {
        console.log("终于完了!");
      });
    }
    init();
  </script>
</html>