代码片段

⌈工具⌋ 在队列中执行异步函数

使用async\await实现队列执行

javascript 复制代码
/**
 * 队列执行函数
 * @param asyncFunction 异步函数
 * @param items  参数数组
 * @param maxConcurrent  最大并发数
 * @returns 结果数组
 */
async executeAsyncFunctionInQueue<T, K>(
  asyncFunction: (item: K, index: number) => Promise<T>,
  items: K[],
  maxConcurrent: number = 10
): Promise<Array<T | Error>> {
  const queue = [...items]
  const results: Array<T | Error> = new Array(items.length)
  const executing = new Set<Promise<void>>()

  const executeNext = async (): Promise<void> => {
    if (queue.length === 0) return

    const currentIndex = items.length - queue.length
    const item = queue.shift()!

    const promise = (async () => {
      try {
        const result = await asyncFunction(item, currentIndex)
        results[currentIndex] = result
      } catch (error) {
        results[currentIndex] =
          error instanceof Error ? error : new Error(String(error))
      }
    })()

    executing.add(promise)
    await promise
    executing.delete(promise)

    if (queue.length > 0) {
      await executeNext()
    }
  }

  const workers = Array.from(
    { length: Math.min(maxConcurrent, queue.length) },
    () => executeNext()
  )

  await Promise.all(workers)
  return results
}

⌈工具⌋ 在队列中执行异步函数

根据传入的函数,及参数数组,按队列执行,并可配置最大同时执行个数。

javascript 复制代码
/**
 * 队列执行函数
 * @param {Function} asyncFunction 异步函数
 * @param {Array} items 数据数组
 * @param {Number} maxConcurrent 最大并行
 * @returns
 */
export function executeAsyncFunctionInQueue(
  asyncFunction,
  items,
  maxConcurrent = 10
) {
  items = items.slice()
  return new Promise((resolve) => {
    const total = items.length
    const results = []
    const executing = new Set()
    const executeNext = async () => {
      if (items.length === 0) {
        return
      }
      const currentIndex = total - items.length
      const item = items.shift()
      const promise = asyncFunction(item, currentIndex)
        .then((result) => {
          results.push(result)
        })
        .catch((error) => {
          results.push(error)
        })
        .finally(() => {
          executing.delete(promise)
          if (executing.size || items.length) {
            executeNext()
          } else {
            resolve(results)
          }
        })
      executing.add(promise)
    }
    while (executing.size < maxConcurrent && items.length > 0) {
      executeNext()
    }
  })
}

整合压缩包下载

将多个在线文件地址,通过压缩包下载。

javascript 复制代码
const script = document.createElement('script')
script.setAttribute(
  'src',
  'https://cdn.bootcdn.net/ajax/libs/jszip/3.10.1/jszip.min.js'
)
// 文件地址
const urls = []
// 压缩包的名字
const name = Date.now()
script.onload = () => {
  const zip = new JSZip()
  Promise.all(
    urls.map((url) => fetch(url).then(res => res.arrayBuffer()))
  ).then((arrayBuffers) => {
    arrayBuffers.forEach((arrayBuffer, index) => {
      const filename = `${index + 1}.${urls[index].split('.').pop()}`
      zip.file(filename, arrayBuffer)
    })
    zip.generateAsync({ type: 'blob' }).then((content) => {
      const link = document.createElement('a')
      link.href = URL.createObjectURL(content)
      link.download = name + '.zip'
      link.click()
    })
  })
}
document.body.appendChild(script)
2024-09-28