实现一个异步求和函数(不改变asyncAdd完善sum)

一、题目:如下为一段代码,请完善sum函数,使得 sum(1,2,3,4,5,6) 函数返回值为 21 ,需要在 sum 函数中调用 asyncAdd 函数,且不能修改asyncAdd函数

/**
 * 请在 sum函数中调用此函数,完成数值计算
 * @param {*} a 要相加的第一个值
 * @param {*} b 要相加的第二个值
 * @param {*} callback 相加之后的回调函数
 */
function asyncAdd(a,b,callback) {
  setTimeout(function(){
   callback(null, a+b)
  },1000)
}

/**
 * 请在此方法中调用asyncAdd方法,完成数值计算
 * @param  {...any} rest 传入的参数
 */
async function sum(...rest) {
  // 请在此处完善代码
}

let start = window.performance.now()
sum(1, 2, 3, 4, 5, 6).then(res => {
  // 请保证在调用sum方法之后,返回结果21
  console.log(res)
  console.log(`程序执行共耗时: ${window.performance.now() - start}`)
})

二、解决

      function asyncAdd(a, b, callback) {
        setTimeout(function () {
          callback(null, a + b);
        }, 1000);
      }

      // 方法一:前面的和加后一个,想当进行 n-1 次运算,应该大于 5秒但小于6秒
      async function sum1(...rest) {
        // 请在此处完善代码
        let result = rest.shift();
        for (let i = 0; i < rest.length; i++) {
          const num = rest[i];
          result = await new Promise((resolve) => {
            asyncAdd(result, num, (_, pre) => resolve(pre));
          });
        }
        return result;
      }

      // 方法二:两个两个拆开来算,然后利用Promise.all()返回数组结果的特性进行递归处理,大于3秒小于4秒
      async function sum2(...rest) {
        // 请在此处完善代码
        // 递归返回条件:传值只有一个的时候,直接输出
        // PS: 对于递归,任何时候都要考虑跳出递归的条件,不能进入死循环
        if (rest?.length <= 1) {
          return rest[0] ?? 0;
        }

        const promises = [];
        for (let i = 0; i < rest.length; i += 2) {
          promises.push(
            new Promise((resolve) => {
              // 偶数个的时候,需要界限判断,直接返回改数值参与下次递归即可
              if (rest[i + 1] === undefined) {
                resolve(rest[i]);
              } else {
                asyncAdd(rest[i], rest[i + 1], (_, pre) => resolve(pre));
              }
            })
          );
        }

        const result = await Promise.all(promises);
        return await sum2(...result); // 一定要继续 return,不然就是 undefined
      }

      // 方法三:几乎并行计算,大于1秒小于2秒,
      // 利用【隐式类型转换, 对象 + 数字,会先调用对象的 toString 方法,重新 toString 每次拿被计算的值参与计算】
      // Promise.all() 是使用微任务队列执行的(即 microtask 的 queue),所以并不是普世定义的并行执行,队列是先进先出是串行的;
      // 因此,每次都更新下面 result 值,从而完成计算,这个是这个方法实现的基础
      async function sum3(...rest) {
        // 请在此处完善代码
        let result = 0;
        const obj = {};
        obj.toString = () => result;
        const promises = [];
        for (let num of rest) {
          promises.push(
            new Promise((resolve) => {
              asyncAdd(obj, num, (_, pre) => resolve(pre));
            }).then((res) => (result = res))
          );
        }

        await Promise.all(promises);
        return result;
      }

      let start = window.performance.now();
      //  这里切换成 sum1, sum2, sum3 即可
      sum3(1, 2, 3, 4, 5, 6).then((res) => {
        // 请保证在调用sum方法之后,返回结果21
        console.log(res);
        console.log(`程序执行共耗时: ${window.performance.now() - start}`);
      });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值