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

addRemote #40

Open
keep-run opened this issue Jul 28, 2021 · 0 comments
Open

addRemote #40

keep-run opened this issue Jul 28, 2021 · 0 comments

Comments

@keep-run
Copy link
Owner

keep-run commented Jul 28, 2021

题目内容

掘金看到一个比较有意思的题目(https://juejin.cn/post/6987529814324281380#heading-11) 。大致的意思就是,需要调用接口计算两个数相加。实现一个函数实现任意个数的数字和。

实现思路

  • 遍历,老老实实的计算。实现方法:
    • for遍历;
    • 递归;
    • reduce遍历;
  • 基于promise.all,串行遍历变为并行;
  • 做本地缓存,避免重复请求(连续执行时,后续可以秒返回)

源代码

// 第一种,普通遍历,串行执行,效率比较低
async function addFn1(args) {
  let res = 0
  for (const item of args) {
    res = await addRemote(res, item)
  }
  return res
}

// 递归实现, 串行执行, 和addFn1差距不大
async function addFn2(args = []) {
  if (args.length < 2) {
    return args[0] || 0
  }
  args.push(await addRemote(args.shift(), args.shift()))
  return addFn2(args)
}

// 基于reduce来实现
async function addFn3(args = []) {
  return args.reduce((calculator, current) => {
    return calculator.then(cal => addRemote(cal, current))
  }, Promise.resolve(0))
}

// 利用promiseAll 两两一组执行
async function addFn4(args = []) {
  let promiseChain = []
  if (args.length % 2) {
    promiseChain.push(Promise.resolve(args.shift()))
  }
  for (let i = 0; i < args.length / 2; i++) {
    promiseChain.push(addRemote(args[2 * i], args[(2 * i) + 1]))
  }
  return Promise.all(promiseChain).then(res => {
    if (res.length === 1) {
      return res[0]
    }
    return addFn4(res)
  })
}

let cache = {}
async function addFn5(args = []) {
  async function addWithCache(params) {
    let promiseChain = []
    if (params.length % 2) {
      promiseChain.push(Promise.resolve(params.shift()))
    }
    for (let i = 0; i < params.length / 2; i++) {
      let key1 = params[2 * i];
      let key2 = params[(2 * i) + 1];
      let cacheRes = cache[`${key1}${key2}`] || cache[`${key2}${key1}`]

      if (cacheRes) {
        promiseChain.push(cacheRes)
      } else {
        promiseChain.push(addRemote(key1, key2).then(res => {
          cache[`${key1}${key2}`] = res;
          return res
        }))
      }
    }
    return Promise.all(promiseChain).then(res => {
      if (res.length === 1) {
        return res[0]
      }
      return addWithCache(res)
    })
  }
  return addWithCache(args)
}

测试

const addRemote = async (a, b) => new Promise(resolve => {
  setTimeout(() => resolve(a + b), 500)
});
async function add(...inputs) {
  console.log('---------------------分割线---Fn1------------------------------')
  console.time('addFn1')
  console.log(await addFn1([...inputs]))
  console.timeEnd('addFn1')
  console.log('---------------------分割线---Fn2------------------------------')
  console.time('addFn2')
  console.log(await addFn2([...inputs]))
  console.timeEnd('addFn2')
  console.log('---------------------分割线---Fn3------------------------------')
  console.time('addFn3')
  console.log(await addFn3([...inputs]))
  console.timeEnd('addFn3')
  console.log('---------------------分割线---Fn4------------------------------')
  console.time('addFn4')
  console.log(await addFn4([...inputs]))
  console.timeEnd('addFn4')
  console.log('---------------------分割线---Fn5------------------------------')
  console.time('addFn5')
  console.log(await addFn5([...inputs]))
  console.timeEnd('addFn5')
  console.log('---------------------分割线---Fn5withcache---------------------')
  console.time('addFn5--again')
  console.log(await addFn5([...inputs]))
  console.timeEnd('addFn5--again')
}

add(1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 10, 10, 10, 10)

时间统计结果
image

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