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

 2022-10-27    410  

题目:

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

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

简化:两数之和

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

functionsumT(a,b){
returnawaitnewPromise((resolve,reject)=>{
asyncAdd(a,b,(err,res)=>{
if(!err){
resolve(res)
}
reject(err)
})
})
}

//测试
consttest=awaitsumT(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 取数组中的第二个值
constarr=[1,2,3,4];
constreducer=(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 次求和:

functionsum(...args){
returnnewPromise(resolve=>{
args.reduce((acc,cur)=>acc.then(total=>sumT(total,cur)),Promise.resolve(0)).then(resolve)
})
}

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

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

console.time("sum")
//测试
awaitsum(1,2,3,4,5)
//15
console.timeEnd("sum")

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

优化:使用 Promise.all

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

asyncfunctionsum(...args){
//用于考察每次迭代的过程
console.log(args)

//如果仅有一个,直接返回
if(args.length===1)returnargs[0]
letresult=[]
//两两一组,如果有剩余一个,直接进入
for(leti=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组内求和
returnsum(...awaitPromise.all(result))
}

//测试
test=awaitsum(1,2,3,4,5)
//15

console.time("sum")
awaitsum(1,2,3,4,5)
console.timeEnd("sum")

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

  •  标签:  
  • MySQL
  •  

原文链接:https://77isp.com/post/10375.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。