All files / utils asyncLimit.ts

100% Statements 18/18
100% Branches 6/6
100% Functions 5/5
100% Lines 18/18

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48                                      11x 11x 11x   11x 16x 16x 16x       11x 32x 16x 16x 16x 16x 16x       11x 16x 16x     11x    
export interface AsyncLimitOptions {
  /**
   * 并行量。
   *
   * @default 1
   */
  concurrency?: number
}
 
/**
 * 异步函数并行执行限制。
 *
 * @param asyncFn 异步函数
 * @param options 选项
 */
export function asyncLimit<T extends (...args: any[]) => Promise<any>>(
  asyncFn: T,
  options: AsyncLimitOptions = {},
): T {
  const { concurrency = 1 } = options
  const queue: Array<[args: any[], resolve: (res: any) => any]> = []
  let activeCount = 0
 
  const call = (...args: any[]) => {
    return new Promise(resolve => {
      queue.push([args, resolve])
      run()
    })
  }
 
  const run = () => {
    if (activeCount < concurrency && queue.length) {
      activeCount++
      const [args, resolve] = queue.shift()!
      const res = asyncFn(...args)
      resolve(res)
      res.then(next, next)
    }
  }
 
  const next = () => {
    activeCount--
    run()
  }
 
  return call as any
}