前言
看到一道有意思的题目:
// 假设本地机器无法做加减乘除运算,需要通过远程请求让服务端来实现。
// 以加法为例,现有远程API的模拟实现
const addRemote = async (a, b) => new Promise(resolve => {
setTimeout(() => resolve(a + b), 1000)
});
// 请实现本地的add方法,调用addRemote,能最优的实现输入数字的加法。
async function add(...inputs) {
// 你的实现
}
// 请用示例验证运行结果:
add(1, 2)
.then(result => {
console.log(result); // 3
});
add(3, 5, 2)
.then(result => {
console.log(result); // 10
})
题目不难,简单答案如下:
async function add(...args) {
let res = 0;
if (args.length <= 2) return res;
for (const item of args) {
res = await addRemote(res, item);
}
return res;
}
递归版本:
async function add(...args) {
let res = 0;
if (args.length === 0) return res;
if (args.length === 1) return args[0];
const a = args.pop();
const b = args.pop();
args.push(await addRemote(a, b));
return add(...args);
}
本文主角
版本:
async function add(...args) {
return args.reduce((promiseChain, item) => {
return promiseChain.then(res => {
return addRemote(res, item);
});
}, Promise.resolve(0));
}
可以看出,最后一个版本的亮点如下:
- Promise链式调用
- reduce的掌握
- async function本质理解
本文只探讨其中的第二点,reduce的掌握
API介绍
reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
参数
1. callback
一个回调函数,一下称这个函数为reducer。
reducer接收四个参数:
- accumulator 累加值
- currentValue 当前正在处理的值,可以理解为遍历(循环)中的item,当前项
- index 当前元素的索引,就是参数2的索引 (可选)
- array 调用reduce的数组 (可选)
2. initialValue (可选)
累加值的初始值,默认为数组的第一项。
这里有一个值得注意的地方:
注意:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。
在我看来,reduce是一个内部封装好的遍历,是另一种形式的forEach,举个例子:
[1,2,3,4,5].reduce((a,b)=>a+b)
上述代码时一个基础的reduce例子,实现一个简单的累加器,执行结果为:1+2+3+4+5 = 15
上述代码因为没有指定InitialValue,所以会执行四次,初次的accumulator为1,currentValue为2;
等同于:
var accumulator = 0;
var demo = [1,2,3,4,5]
demo.forEach((item)=>{
accumulator += item
})
console.log(accumulator); // 15
题目及其答案出处:今天聊:大厂如何用一道编程题考察候选人水平
个人学习记录,参考自: Reduce API