【JS】并发控制

36 阅读1分钟

/**
* 控制并发
* @param {Function} fn 逻辑处理函数
* @param {Array} arr 发送的数据
* @param {Number} [max=3] 并发数 默认3
* @param {Number} [order=false] 按顺序返回执行结果 默认false
* @param {Number} [retry=1] 重试次数 默认1
* @returns {Promise} 返回Promise
*/
const reqPool = (fn, arr, max = 3, order = false, retry = 1) => {
    let reqList        = [...arr],                                        //不改变arr
        resData        = order ? Array(reqList.length).fill(0, 0) : [],   //  order = true 填充返回的数据
        curRuningCount = 0,                                               //限制内的第n个并发 
        runedCount     = 0,                                               //已执行的数量                         
        runingIndex    = 0;                                               //当前执行下标                       

    return new Promise(res => {
        const run = _ => {
            while (curRuningCount < max && reqList.length) {
                curRuningCount++
                const chunk = reqList.shift();
                (i => {
                    /**
                 * 当前重试次数 
                 */
                    let _retry = 0
                    const add = (i2, data) => fn(data)
                        .then(r => {
                            runedCount++
                            order ? resData[i2] = r : resData.push(r)
                        })
                        .catch(err => {
                            _retry++
                            const repMore = _retry > retry
                            if (!repMore) {
                                add(i2, data)
                                console.log(data, '重试' + _retry + '次');
                            } else {
                                order ? resData[i2] = err : resData.push(err)
                                runedCount++
                            }
                        })
                        .finally(_ => {
                            curRuningCount--
                            if (runedCount === arr.length) res(resData)
                            run()
                        });
                    add(i, chunk)
                })(runingIndex++)
            }
        }
        run()
    })
}

// 请求配置 | 请求体
const chunks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

/**
* 逻辑处理函数 | 如:发起请求
* @param {Object} chunk
* @returns {Promise} 
*/
const req = chunk => new Promise((res, rej) => setTimeout(_ => Math.random() > .8 ? rej('失败----' + chunk) : res('结果' + chunk), Math.random() * 100 + 100))

reqPool(req, chunks, 3, true).then(res => console.log(res))

转自

转自:t.csdnimg.cn/TocBe