Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

实现一个异步求和函数 #109

Open
sisterAn opened this issue May 26, 2021 · 0 comments
Open

实现一个异步求和函数 #109

sisterAn opened this issue May 26, 2021 · 0 comments

Comments

@sisterAn
Copy link
Owner

简化:两数之和

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

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 可选,

  • 如果有 initialValueacc 取值为 initialValuecur 取数组中的第一个值
  • 如果没有: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")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant