首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >一道字节笔试题,实现一个异步求和函数

一道字节笔试题,实现一个异步求和函数

作者头像
用户3806669
发布2021-07-06 14:24:11
发布2021-07-06 14:24:11
7490
举报
文章被收录于专栏:前端三元同学前端三元同学

面试官也在看的前端面试资料

题目:

提供一个异步 add 方法如下,需要实现一个 await sum(...args) 函数:

代码语言:javascript
复制
function asyncAdd(a, b, callback) {
  setTimeout(function () {
    callback(null, a + b);
  }, 1000);
}

简化:两数之和

我们先来简单的实现一个异步两数之和函数

代码语言:javascript
复制
function sumT(a, b) {
    return await new Promise((resolve, reject) => {
        asyncAdd(a, b, (err, res) => {
            if(!err) {
                resolve(res)
            }
            reject(err)
        })
    })
}

// 测试
const test = await sumT(1, 2)
console.log(test)
// 3

加深:多数之和

上面我们实现了两数之和,然后扩展到多数之和喃?

提到数组求和问题,我们首先想到的是 reduce

reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。 —— MDN

代码语言:javascript
复制
arr.reduce(callback(acc, cur[, idx[, arr]])[, initialValue])

callback 函数接收4个参数:

  • acc :累计器
  • cur :当前值
  • idx :当前索引
  • arr :源数组

其中, initialValue 可选,

  • 如果有 initialValueacc 取值为 initialValuecur 取数组中的第一个值
  • 如果没有:acc 取数组中的第一个值, cur 取数组中的第二个值
代码语言:javascript
复制
const arr = [1, 2, 3, 4];
const reducer = (acc, cur) => acc + cur;

// 1 + 2 + 3 + 4
console.log(arr.reduce(reducer));
// 输出: 10

// 5 + 1 + 2 + 3 + 4
console.log(arr.reduce(reducer, 5));
// 输出: 15

关于本题:来自@champkeh

设置初始值为 Promise.resolve(0) ,经历 5 次求和:

代码语言:javascript
复制
function sum(...args) {
    return new Promise(resolve => {
        args.reduce((acc, cur) => acc.then(total => sumT(total, cur)), Promise.resolve(0)).then(resolve)
    })
}

// 测试
await sum(1, 2, 3, 4, 5)
// 15

但这存在一个耗时较长的问题,我们可以计算下时间:

代码语言:javascript
复制
console.time("sum")
// 测试
await sum(1, 2, 3, 4, 5)
// 15
console.timeEnd("sum")

也就是说,我们每次求和都会花费 1s,串行异步求和,这显然不是最优的

优化:使用 Promise.all

我们可以两两一组,使用 Promise.all 求和,再把和两两一组继续求和…..,知道只剩余一个就是最终的结果

代码语言:javascript
复制
async function sum(...args) {
    // 用于考察每次迭代的过程
    console.log(args) 
    
    // 如果仅有一个,直接返回
    if(args.length === 1) return args[0]
    let result = []
    // 两两一组,如果有剩余一个,直接进入
    for(let i = 0; i < args.length - 1; i+=2) {
        result.push(sumT(args[i], args[i + 1]))
    }
    if(args.length%2)  result.push(args[args.length-1])
    // Promise.all 组内求和
    return sum(...await Promise.all(result))
}

// 测试
test = await sum(1, 2, 3, 4, 5)
// 15
代码语言:javascript
复制
console.time("sum")
await sum(1, 2, 3, 4, 5)
console.timeEnd("sum")

来自:https://github.com/Advanced-Frontend/Daily-Interview-Question

最后

欢迎关注「三分钟学前端」,回复「交流」自动加入前端三分钟进阶群,每日一道编程算法面试题(含解答),助力你成为更优秀的前端开发!

》》面试官也在看的前端面试资料《《

“在看和转发”就是最大的支持

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端三元同学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简化:两数之和
  • 加深:多数之和
  • 优化:使用 Promise.all
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档