Skip to content

promise

思考题

  1. 现有 100 个接口数据请求,请你设计一套方案获取这些数据,维持并发为 5,全部数据请求完毕打印结果数组 result (为方便测试,可用 setTimeout 模拟数据请求过程,另:需考虑个别接口请求失败的情况)
参考答案 👀

以下是一套可行方案:

js
const MAX_CONCURRENT_REQUESTS = 5
const TOTAL_REQUESTS = 100

// 模拟数据请求函数,使用setTimeout来模拟延迟,随机失败
function fetchData(url) {
  return new Promise((resolve, reject) => {
    const delay = Math.floor(Math.random() * 500) + 500 // 模拟0.5到1秒的随机延迟
    setTimeout(() => {
      if (Math.random() < 0.1) {
        // 模拟10%的失败率
        reject(`Failed to fetch ${url}`)
      } else {
        resolve(`Data from ${url}`)
        console.log(url, 'ok')
      }
    }, delay)
  })
}

async function fetchAllData(urls) {
  const results = []
  const executing = new Set()

  for (const url of urls) {
    const promise = fetchData(url)
      .then(data => {
        results.push(data)
      })
      .catch(error => {
        console.error(error) // 打印错误信息
        results.push(null) // 也可以选择其他方式处理失败的请求
      })
      .finally(() => {
        executing.delete(promise)
      })

    executing.add(promise)

    if (executing.size >= MAX_CONCURRENT_REQUESTS) {
      await Promise.race(executing)
    }
  }

  // 等待所有剩余的promise完成
  while (executing.size > 0) {
    await Promise.race(executing)
  }

  return results
}

// 生成100个示例URL
const urls = Array.from(
  { length: TOTAL_REQUESTS },
  (_, i) => `https://example.com/data/${i}`
)

fetchAllData(urls)
  .then(results => {
    console.log('All data fetched:', results.length) // 确认结果数量
    console.log('Results:', results) // 打印所有结果,包括失败的
  })
  .catch(error => {
    console.error('Error fetching all data:', error)
  })