异步求和
题目描述
假设客户端不支持加法计算,服务端提供了接口 asyncAdd
,用于计算两个整数的和。asyncAdd
的定义如下:
function asyncAdd(a: number, b: number, cb: (result: number) => void): void {
setTimeout(() => cb(a + b), 50);
}
请实现一个异步求和函数 sum
, 使得 sum(1, 2, 3).then(result => console.log(result))
能够输出 6
。
示例:
sum(1, 2, 3).then(result => console.log(result)); // 6
sum(1, 2, 3, 4).then(result => console.log(result)); // 10
sum(1, 2, 3, 4, 5).then(result => console.log(result)); // 15
进阶:
你可以通过并行调用的方式来优化请求时间吗,请注意浏览器可能会有最大并行请求限制。
解法一:串行调用
思路
可以使用递归来解决这个问题。具体来说,可以将数组 arr
分为两部分,分别计算左半部分和右半部分的和,然后将两部分的和相加。
代码
回调函数实现
function asyncAdd(a: number, b: number, cb: (result: number) => void): void {
setTimeout(() => {
cb(a + b);
}, 1000);
}
function sum(...args: number[]): Promise<number> {
return new Promise((resolve, reject) => {
if (args.length === 0) {
resolve(0);
} else if (args.length === 1) {
resolve(arr[0]);
} else {
asyncAdd(args[0], args[1], (result) => {
sum(result, ...args.slice(2)).then(resolve);
});
}
});
}
Promise 递归实现
function asyncAdd(a: number, b: number, cb: (result: number) => void): void {
setTimeout(() => cb(a + b), 50);
}
function sumTwo(a: number, b: number): Promise<number> {
return new Promise<number>(resolve =>
asyncAdd(a, b, result => resolve(result)),
);
}
export function sum(...args: number[]): Promise<number> {
if (args.length === 0) return Promise.resolve(0);
if (args.length === 1) return Promise.resolve(arr[0] || 0);
const [a = 0, b = 0, ...rest] = args;
return sumTwo(a, b).then((result) => {
if (rest.length === 0) return result;
return sum(result, ...rest);
});
}
async/await 递归实现
function asyncAdd(a: number, b: number, cb: (result: number) => void): void {
setTimeout(() => cb(a + b), 50);
}
function sumTwo(a: number, b: number): Promise<number> {
return new Promise<number>(resolve =>
asyncAdd(a, b, result => resolve(result)),
);
}
export async function sum(...arr: number[]): Promise<number> {
if (arr.length === 0) return 0;
if (arr.length === 1) return arr[0] || 0;
const [a = 0, b = 0, ...rest] = arr;
const result = await sumTwo(a, b);
return rest.length === 0 ? result : sum(result, ...rest);
}
async/await 非递归实现
function asyncAdd(a: number, b: number, cb: (result: number) => void): void {
setTimeout(() => cb(a + b), 50);
}
function sumTwo(a: number, b: number): Promise<number> {
return new Promise<number>(resolve =>
asyncAdd(a, b, result => resolve(result)),
);
}
export async function sum(...args: number[]): Promise<number> {
const results = [...args];
while (result.length > 1) {
const [a = 0, b = 0] = result.splice(0, 2);
results.push(await sumTwo(a, b));
}
return results[0] || 0;
}
解法二:并行调用
思路
将数组每两个元素分为一组,然后并行调用 asyncAdd
函数,最后将结果相加。