首页前端工具函数并发任务控制

并发任务控制

分类前端工具函数时间2025-03-07 16:02:03发布RustStream浏览69
摘要:代码结构 timeout函数 返回一个 Promise,在指定时间后 resolve。 SuperTask类 属性 maxParallelCount:最大并发数。 taskList:待执行任务队列。 currentTask:当前运行任务数。 方法 add(task :将任务包装成 Promise,加入队列,并触发任务执行。 _run( :根据并发限制从队列中取出任务执行,并在任务完成后触发后续任务。 addTask函数 调用 SuperTask 实例添加任务,并在任务完成后打印日志。...

代码结构

timeout函数

  • 返回一个 Promise,在指定时间后 resolve。

SuperTask

属性

  • maxParallelCount:最大并发数。
  • taskList:待执行任务队列。
  • currentTask:当前运行任务数。

方法

  • add(task):将任务包装成 Promise,加入队列,并触发任务执行。
  • _run():根据并发限制从队列中取出任务执行,并在任务完成后触发后续任务。

addTask函数

  • 调用 SuperTask 实例添加任务,并在任务完成后打印日志。

执行流程分析

  1. 初始化:创建 SuperTask 实例,设置最大并发数为 2。
  2. 添加任务:依次添加 6 个任务(每个任务通过 timeout(100000) 模拟耗时操作)。
  3. 任务调度
    • 第一批次:任务 1 和任务 2 立即执行(currentTask 从 0 增至 2)。
    • 剩余任务(3-6)暂存于 taskList
  4. 任务完成处理
    • 任一任务完成时,currentTask 减 1,并调用 _run() 启动新任务。
    • 后续任务按队列顺序依次执行,始终保持最多 2 个任务并发。

并发控制逻辑

  • _run() 方法:通过循环检查并发数和队列长度,逐个取出任务执行。
    • 每个任务执行后,通过 finally 确保无论成功与否都更新状态并触发后续任务。
  • 队列管理:任务按添加顺序执行,确保先进先出(FIFO)。

时间与输出分析

时间线

0-100 秒:任务 1 和任务 2 并行执行,100 秒后同时完成。
100-200 秒:任务 3 和任务 4 启动并执行,完成后触发输出。

  • 200-300 秒:任务 5 和任务 6 启动并执行,完成后触发输出。

输出顺序

  • 每组任务的完成日志按添加顺序输出(如任务 1 和 2 几乎同时完成,但 .then() 回调按任务触发顺序执行)。

潜在问题

  1. 输出顺序确定性
    • 虽然任务按批次完成,但同一批次内(如任务 1 和 2)的日志输出顺序可能受事件循环影响,不过代码逻辑保证了任务按添加顺序执行。
  2. 错误处理
    • 任务失败时仍会触发后续任务,符合预期。

结论

  • 代码正确实现了并发控制,确保最多 2 个任务同时运行,任务按添加顺序分批次执行。
  • 测试用例中的 6 个任务将分三批完成,每批耗时约 100 秒,总时间约 300 秒,输出顺序按任务编号递增。
// 并发任务控制

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

class SuperTask{
    constructor(maxParallelCount = 2){
        this.maxParallelCount = maxParallelCount; // 最大并发数
        this.taskList = []; // 任务列表
        this.currentTask = 0;   // 正在运行数量
    }

    add(task){
        return new Promise((resolve, reject) => {
            this.taskList.push({task, resolve, reject})
            this._run();
        })
    }

    _run(){
        while(this.currentTask < this.maxParallelCount && this.taskList.length){
            const {task, resolve, reject} = this.taskList.shift()
            this.currentTask++;
            Promise.resolve(task()).then(resolve, reject).finally(() => {
                this.currentTask--;
                this._run()
            })            
        }
    }
}


const superTask = new SuperTask();

function addTask(time, task){
    superTask
    .add(()=>{timeout(time)})
    .then(()=>{
        console.log(`任务${task}完成`)
    })
}


addTask(100000, 1);
addTask(100000, 2);
addTask(100000, 3);
addTask(100000, 4);
addTask(100000, 5);
addTask(100000, 6);

本文链接:https://blog.smallhao.fun/?id=14 转载需授权!

分享到:

Chen’Blog版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

JavaScript
消除异步函数的传染性 uni-app实现仿美团商品左右菜单联动效果

游客 回复需填写必要信息
召唤伊斯特瓦尔