【前端】js 多个并行的Promise阻塞工具 限制并行执行数量

“多线程”Promise 工具类

方案一 推荐


    // 最大并发限制数
    const 最大并发限制数 = 5;
    
    // 创建一个计数器,用于限制并发请求数量
    var 当前并行数量 = 0;

    // 请求列表
    const 请求列表 = [];

    // 成功回调函数
    const callback = (request) => {
        console.log('当前并行数量:' + 当前并行数量 + " 请求结束:", request);
    };
    
    
    for (let i = 0; i < 15; i++) {
        请求列表.push('请求' + i)
    }

    // 成功回调函数
    const 开始 = async () => {
        // 发送请求
        await sendRequest(请求列表, 最大并发限制数, callback);
        console.log('全部执行完毕')
        console.log('执行最后一个请求完成')
    };

    //开始
    开始()
    
    
    
    /**
     * 并行发送请求
     * @param 请求列表
     * @param limits        并行上限
     * @param callback      回调
     * @returns {Promise<void>}
     */
    async function sendRequest(请求列表, 最大并发限制数, callback) {
        //单个的请求方法
        const 执行请求 = async (request) => {
            // 执行请求的逻辑,这里使用console.log语句作为示例
            console.log('当前并行数量:' + 当前并行数量 + " 请求开始,入参:", request);
            try {
                // 模拟请求的异步执行
                let res = await new Promise((resolve) => setTimeout(()=>{resolve(request+"-返回值:成功")}, 3000));
                // 请求完成后调用回调函数
                callback({入参:request, 状态:true, 返回值:res});
            }catch (e) {
                // 出错
                callback({入参:request, 状态:false, 异常:e});
            }
        };
        // 创建一个计数器,用于限制并发请求数量
        当前并行数量 = 0;
        // const controlConcurrency = async () => {
        //     while (当前并行数量 < 最大并发限制数 && 请求列表.length > 0) {
        //         const 请求 = 请求列表.shift(); // 取出下一个请求
        //         当前并行数量++;
        //         await 执行请求(请求); // 执行请求
        //         当前并行数量--;
        //     }
        //
        //     // 检查是否还有未完成的请求
        //     if (当前并行数量 === 0 && 请求列表.length === 0) {
        //         callback(); // 所有请求完成后调用回调函数
        //     }
        // };

        // 启动并发控制
        // for (let i = 0; i < 最大并发限制数; i++) {
        //     controlConcurrency();
        // }
        
        let promiseArr = []
        // 启动并发控制
        for (let i = 0; i < 最大并发限制数; i++) {
            // 并发控制函数
            const promise = new Promise(async (resolve) => {
                while (当前并行数量 < 最大并发限制数 && 请求列表.length > 0) {
                    const 请求 = 请求列表.shift(); // 取出下一个请求
                    当前并行数量++;
                    await 执行请求(请求); // 执行请求
                    当前并行数量--;
                }
                // 检查是否还有未完成的请求
                if (当前并行数量 === 0 && 请求列表.length === 0) {
                    callback(); // 所有请求完成后调用回调函数
                }
                //当前结束
                resolve()
            });
            promiseArr.push(promise)
        }
        //等待全部结束
        await Promise.all(promiseArr)
        console.log('启动并发控制执行完毕')
    }

//方案二

vue

that = this

或者用 全局变量

map = {count:0}

//阻塞并获取额度
await WTool.Thread.sleepLimit(that, '变量名称', 500)

await WTool.Thread.sleepLimit(map, 'count', 500)

  Thread:{
    /**
     * 阻塞x毫秒
     * 使用方法
     * await sleep(5000)  等待5秒
     * @param time
     * @returns {Promise<void>}
     */
    async sleep(time){
      await new Promise(resolve => setTimeout(resolve, time))
    },
    /**
     * 阻塞获取额度
     * 使用方法
     * await sleepLimit(that, 字段, 1000)
     * @param _vm     that
     * @param field   字段
     * @param time   多久判断一次
     * @returns {Promise<boolean>}
     */
    async sleepLimit(_vm, field, time){
      if(time){
        time = 500
      }
      let flag = true
      while(flag){
        if(_vm[field] > 0){
        // if(_vm[field].length > 0){
          //睡眠等待
          await WTool.Thread.sleep(time);

          //有额度了
          flag = false
          _vm[field]--
          // _vm[field].shift()
          console.log('有额度了,获取名额之后:',_vm[field])
          return true
        }else{
          //睡眠等待
          await WTool.Thread.sleep(time);
        }
      }

    },
    /**
     * 等待额度释放完毕
     * 使用方法
     * await join(that, 字段, 1000)
     * @param _vm     that
     * @param field   字段
     * @param time   多久判断一次
     * @returns {Promise<boolean>}
     */
    async join(_vm, field, realCount, time){
      if(time){
        time = 2000
      }
      let flag = true
      while(flag){
        if(_vm[field] >= realCount){
        // if(_vm[field].length >= realCount){
          console.log('所有额度释放完毕:',_vm[field])
          //有额度了
          flag = false
          return true
        }else{
          //睡眠等待
          await WTool.Thread.sleep(time);
        }
      }

    }

  },

核心就是阻塞  等待其他完成

其他方案   

参考

浅谈JS阻塞方式怎么实现异步任务队列?-云搜网 (27ka.cn)

let queue = []
let index = 0
function clickMe() {
    queue.push({
        name: 'click',
        index: index++
    })
}
run()
async function run() {
    while (true) {
        if (queue.length > 0) {
            let obj = queue.shift()
            let res = await request(obj.index)
            console.log('已处理事件' + res)
        } else {
            await wait(500)
            console.log('----- 队列空闲中 -----')
        }
    }
}
// 通过setTimeout模拟异步请求
function request(index) {
    return new Promise(function (resolve, reject) {
        setTimeout(() => {
            resolve(index)
        }, 1000)
    })
}

function wait(time) {
    return new Promise(function (resolve) {
        setTimeout(() => {
            resolve()
        }, time)
    })
}

其他方案

// 异步请求队列 
const queue = []
// 用来模拟不同的返回值 let index = 0
// 标志是否正在处理队列中的请求
let running = false
// 使用setTimeout模拟异步请求
function request(index) {
    return new Promise(function (resolve) {
        setTimeout(() => {
            resolve(index)
        }, 1000)
    })
}
// 连续点击,触发异步请求,加入任务队列
function clickMe() {
    addQueue(() => request(index++))
}
// 当队列中任务数大于0时,开始处理队列中的任务 
function addQueue(item) {
    queue.push(item)
    if (queue.length > 0 && !running) {
        running = true
        process()
    }
}

function process() {
    const item = queue.shift()
    if (item) {
        item().then(res => {
            console.log('已处理事件' + res)
            process()
        })
    } else {
        running = false
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Promise.all 的性能更高,因为它可以并行执行多个 Promise,而一个个写 Promise 则是串行执行,需要等待前一个 Promise 完成后才能执行下一个 Promise。这意味着 Promise.all 可以更快地完成多个异步任务。 ### 回答2: Promise.all的性能更高。原因如下: 1. 并行执行Promise.all能同时执行多个Promise,而不需要等待之前的Promise完成后再执行下一个。相比之下,一个个写Promise则是按照顺序一个一个执行,需要等待上一个Promise完成后才能执行下一个,不能并行执行。 2. 单次错误处理: Promise.all只需要一次错误处理,如果其中任意一个Promise发生错误,就会立即返回错误信息。而一个个写Promise则需要每个Promise都进行错误处理,增加了代码量和复杂度。 3. 性能优化:Promise.all能够利用浏览器或Node.js的异步执行能力,可以更好地利用计算机的资源和性能,执行效率高。而一个个写Promise则会阻塞后续的代码执行,降低性能。 4. 代码简洁:Promise.all使用简洁、清晰的语法,将多个Promise放入一个数组中传入,一次性处理多个异步操作,代码结构清晰易读。而一个个写Promise则需要逐个处理,代码冗余,可读性较差。 综上所述,Promise.all相比一个个写Promise,在性能、错误处理、性能优化和代码简洁性等方面都更优。 ### 回答3: Promise.all和一个个写Promise的性能取决于具体的场景和代码实现。 在某些情况下,Promise.all可能比一个个写Promise更高效。因为Promise.all可以同时处理多个Promise对象,并在它们全部完成后返回结果。这在需要等待多个异步操作完成后再进行后续操作的情况下非常有用,可以极大地提高代码的性能和效率。 相比之下,一个个写Promise需要依次执行每个异步操作,并等待每个操作的结果返回后再进行下一个操作。这样的处理方式会导致代码的执行时间比较长,性能较低。 然而,在某些情况下,一个个写Promise可能更合适。比如,在某些业务场景中,我们可能不需要等待所有的异步操作都完成后再进行后续操作,而是可以根据具体的情况选择性地等待某个或某些异步操作的结果。这样,使用一个个写Promise可以更灵活地控制代码的执行顺序和逻辑。 因此,要根据具体的需求和场景来选择使用Promise.all还是一个个写Promise。在需要同时处理多个异步操作并等待它们全部完成后再进行后续操作的情况下,Promise.all更高效;而在需要灵活控制异步操作的执行顺序和逻辑的情况下,一个个写Promise更合适。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是Superman丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值