跳至主要內容

并发请求

yyshino大约 1 分钟FrontEndJS手写系列

    /**
     * 在某些场景下,页面的请求数可能会有很多,
     * 比如:抓取、分片上传等,如果我们需要等一个请求完成后,
     * 再发起下一个请求,是必效率会比较低。
     * 为了提升效率,我们可以同时发出多个请求,但数量又不能太多,
     * 如若某请求完成,剩余等待的请求继续补位执行,
     * 将请求的结果(不论成功或失败),按原有数组的顺序返回。
     */

    /**
     * 11-并发事件
     * @param {string[]} urls 请求地址数组
     * @param {number} max 最大并发数
     */
    function consurRequest(urls, max) {
        return new Promise((resolve,reject) => {
            // 判断传入urls长度,为空直接返回[]
            if(urls.length === 0){
                resolve([])
                return
            }

            const results = []
            let count = 0 // 标识请求的完成数量
            let index = 0 // 下一个请求

            // 发送请求
            async function request(){
                // 退出逻辑
                if(index === urls.length){
                    return
                }

                // 存储 index,保持后续请求结果数组与urls数组对应
                const i = index
                const url = urls[index]
                index++
                try {
                    const resp = await fetch(url)
                    // resp加入到 results中
                    results[i] = resp
                } catch (err) {
                    // err 加入到results
                    results[i] = err
                    console.log('err',err)
                } finally {
                    // 判断是否所以的请求都完成
                    count++
                    // if(count === urls.length){
                    if(count === urls.length){
                        resolve(results)
                        return
                    }
                    request()
                }
            }

            const times = Math.min(max,urls.length)
            let promiseList = []

            for(let i = 0; i < times; i++){
                promiseList.push(request())
            }

            Promise.race(promiseList).then(() => {
            }).catch((err) => {
                reject(err)
            })
        })
    }