AwesomeDevin/blog

请实现一个函数 schedule 以限制最大并发任务数

Opened this issue · 0 comments

针对fn1fn2fn3fn4实现一个异步并发队列函数schedule(n),保证以下输出:

  • n = 1时,输出结果(1,2,3,4)分别相距 2秒/3秒/4秒
  • n = 2时,输出结果(1,2,3,4)分别相距 1秒/2秒/2秒
  • n = 3时,输出结果(1,2,3,4)分别相距 1秒/1秒/2秒
  • n >= 4时,输出结果(1,2,3,4)分别相距 1秒/1秒/1秒

思路:

  1. 小于 n 任务为同步执行任务,大于 n 任务为异步执行任务
  2. 实现一个同步队列
  3. 实现一个异步队列
  4. 同步队列执行完成后取异步队列任务执行

实现如下:

const fn1 = ()=>new Promise((resolve)=>{
  setTimeout(()=>{
    resolve(1)
  },1000)
})
      
const fn2 = () => new Promise((resolve)=>{
  setTimeout(()=>{
    resolve(2)
  },2000)
})

const fn3 = () => new Promise((resolve)=>{
  setTimeout(()=>{
    resolve(3)
  },3000)
})

const fn4 = () => new Promise((resolve)=>{
  setTimeout(()=>{
    resolve(4)
  },4000)
})

function schedule(max){
  const queue = []
  const asyncQueue = []
  let count = 0
  let cur = null
  
  function push(fn){
    queue.push(fn)
  }
  
  function pop(){
    return queue.shift()
  }
  
  function execute(task){
    count++
    return task().then(res=>{
      count--
      const cur = asyncQueue.shift()
      const next = cur?.next
      const asyncResolve = cur?.resolve
      if(asyncResolve && next){
        next().then(res=>{
          asyncResolve(res)
        })
      }
      return res
    })
  }
  
  function next(){
    const cur = pop()
    return execute(cur)  
  }
  
  function run(){
    return count < max ? next() :  new Promise((resolve)=>{
      asyncQueue.push({
        next: next,
        resolve
      })
    })
  }
  
  return {
    push, run
  }
}

const sd = schedule(1)

sd.push(fn1)
sd.push(fn2)
sd.push(fn3)
sd.push(fn4)

sd.run().then(res=>{
  console.log(res, new Date().getSeconds())
})
sd.run().then(res=>{
  console.log(res, new Date().getSeconds())
})
sd.run().then(res=>{
  console.log(res, new Date().getSeconds())
})
sd.run().then(res=>{
  console.log(res, new Date().getSeconds())
})

运行:
n = 1时,输出结果(1,2,3,4)分别相距 2秒/3秒/4秒:
image.png