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

不使用加号 + 实现异步相加函数 #57

Open
Inchill opened this issue Apr 9, 2024 · 0 comments
Open

不使用加号 + 实现异步相加函数 #57

Inchill opened this issue Apr 9, 2024 · 0 comments

Comments

@Inchill
Copy link
Owner

Inchill commented Apr 9, 2024

不使用加号 + 实现异步相加函数

题目描述

给定一个辅助函数如下:

function asyncAdd(a, b, callback) {
    setTimeout(function() {
        callback(a + b)
    }, 1000)
}

在不使用加号 + 的情况下,实现一个函数,实现两个异步相加,返回一个异步结果。示例如下:

sum(1,2,3,4,5,6,7,8,9,10,11).then(sum => console.log(sum))

思路

先说下整体思路,不能使用加号的话,那就只能借助辅助函数来完成运算。因为最终返回的是 Promise,所以一开始想到的就是需要对辅助函数进行包装,使得从语言层面能异步控制它。接下来就是对参数个数进行分析,理想状态下就是对参数不停地进行二分操作,降低时间复杂度,将其变为 O(log n) 就是最佳时间。在二分地过程中,涉及到递归,递归终止条件就是只有一个参数,这时候就可以直接返回。如果是还剩 2 个参数,调用包装过的辅助函数,返回一个 Promise,然后通过 then 链式调用,将结果返回。

代码实现

function asyncAdd(a = 0, b = 0, callback) {
    setTimeout(function() {
        callback(a + b)
    }, 1000)
}

const add = (a = 0, b = 0) => new Promise((resolve) => asyncAdd(a, b, resolve));

function sum(...args) {
    if (args.length === 1) return new Promise((resolve) => resolve(args));
    if (args.length === 2) {
        return new Promise((resolve) => asyncAdd(args[0], args[1], resolve));
    }

    let params = [];
    for (let i = 0; i < args.length; i += 2) {
        if (i + 1 < args.length) {
            params.push([args[i], args[i + 1]]);
        } else {
            params.push([args[i]]);
        }
    }

    let fns = []

    params.forEach(([a, b]) => {
        fns.push(add(a, b));
    });

    return Promise.allSettled(fns).then((res) => {
        const answers = res.map(item => item.value);
        console.log(answers)
        return sum(...answers);
    })
}

测试

const start = Date.now();
sum(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25).then(sum => {
    const end = Date.now()
    console.log('sum =', sum)
    console.log(`time = ${(end - start) / 1000}s`)
})

// [
//    3,  7, 11, 15, 19, 23,
//   27, 31, 35, 39, 43, 47,
//   25
// ]
// [
//   10, 26, 42, 58,
//   74, 90, 25
// ]
// [ 36, 100, 164, 25 ]
// [ 136, 189 ]
// sum = 325
// time = 5.018s

可以看到,在时间上并不是串行的 25 秒,而是 5 秒,极大地提升了运算速度。

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