Last updated on

实现并发请求控制

Q

请写一个函数  limitedConcurrentReqs(reqUrls, limit)  实现最大并发数的并发请求。不管请求成功还是失败,都当作结果返回,最后返回一个结果数组,对应每个  reqUrl  的请求结果。

A

算是 Promise all 的进阶版吧

const randomRequest = (url, success) => {
    return new Promise<string>((resolve, reject) => {
        setTimeout(() => {
            success ? resolve(`url: ${url} res`) : reject(`reject ${url}`)
        }, 100);
    })
}

const limitedConcurrentReqs = async (reqUrls: string[], limit: number) => {
    if (limit <= 0) {
        throw new Error(`Invalid limit: ${limit}`)
    }

    return new Promise((resolve) => {
        const results: string[] = []
        let nextIndex = 0
        let completedCount = 0

        const processRequest = async () => {
            const currentIndex = nextIndex
            nextIndex += 1
            if (currentIndex >= reqUrls.length) return

            try {
                const result = await randomRequest(reqUrls[currentIndex], Math.random() > 0.5)
                results[currentIndex] = result
            } catch (error) {
                results[currentIndex] = error
            }

            completedCount += 1

            if (completedCount === reqUrls.length) {
                resolve(results)
                return
            }

            // Process next request if any remaining
            processRequest()
        }

        // Initialize concurrent requests up to the limit
        const initialCount = Math.min(limit, reqUrls.length)
        for (let i = 0; i < initialCount; i++) {
            processRequest()
        }
    })
}

console.time()
console.log(await limitedConcurrentReqs(Array.from({ length: 5 }).map((_, index) => `${index}`), 2))
console.timeEnd()
[ "reject 0", "url: 1 res", "reject 2", "reject 3", "url: 4 res" ]
[312.39ms] default