简化:两数之和
我们先来简单的实现一个异步两数之和函数
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
arr.reduce(callback(acc, cur[, idx[, arr]])[, initialValue])
callback
函数接收4个参数:
acc
:累计器cur
:当前值idx
: 当前索引arr
:源数组
其中, initialValue
可选,
- 如果有
initialValue
:acc
取值为initialValue
,cur
取数组中的第一个值 - 如果没有:
acc
取数组中的第一个值,cur
取数组中的第二个值
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
次求和:
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
但这存在一个耗时较长的问题,我们可以计算下时间:
console.time("sum")
// 测试
await sum(1, 2, 3, 4, 5)
// 15
console.timeEnd("sum")
也就是说,我们每次求和都会花费 1s,串行异步求和,这显然不是最优的
优化:使用 Promise.all
我们可以两两一组,使用 Promise.all
求和,再把和两两一组继续求和…..,知道只剩余一个就是最终的结果
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
console.time("sum")
await sum(1, 2, 3, 4, 5)
console.timeEnd("sum")
最后
本文首发自「三分钟学前端」,回复「交流」自动加入前端三分钟进阶群,每日一道编程算法面试题(含解答),助力你成为更优秀的前端开发! 号内回复「网络」,自动获取三分钟学前端网络篇小书(90+页) 号内回复「JS」,自动获取三分钟学前端 JS 篇小书(120+页) 号内回复「算法」,自动获取 github 2.9k+ 的前端算法小书 号内回复「面试」,自动获取 github 23.2k+ 的前端面试小书 号内回复「简历」,自动获取程序员系列的 120 套模版 最近开源了一个github仓库:百问百答,在工作中很难做到对社群问题进行立即解答,所以可以将问题提交至 https://github.com/Advanced-Frontend/Just-Now-QA ,我会在每晚花费 1 个小时左右进行处理,更多的是鼓励与欢迎更多人一起参与探讨与解答🌹