首页 > 其他分享 >JS实现任务队列

JS实现任务队列

时间:2023-09-21 23:35:10浏览次数:47  
标签:顺序 队列 JS 任务 resolve let 执行

引言

假设有这么一个场景:

  • 前端订阅后台数据的变化,如果发生变化,则触发订阅回调;
  • 回调函数中,会执行一些耗时操作,如:请求接口,发送短信,存历史数据等;
  • 要求以上所有的操作都必须按照订阅触发的顺序执行;

我们都知道,回调本身就是一种异步操作,我们仅仅依靠订阅回调无法保证回调中任务执行顺序的。

为了解决这个问题,我们可以使用任务队列,将回调函数添加到任务队列中,然后按照顺序依次执行。

任务队列的概念

顾名思义,任务队列就是存放任务的队列,队列中的任务都严格按照进入队列的先后顺序执行。

在前一条任务执行完毕后,立即执行下一条任务,直到任务队列清空。

任务队列的基本执行流程如下:

  • 给任务队列添加任务,并判断执行标识;
  • 如果执行标识为 false,则将任务从队列中独立出来;
  • 开始执行任务,将执行标识置为 true;
  • 执行完毕后,判断队列是否为空,如果不为空,则继续执行下一条任务;
  • 直至任务队列清空。

任务队列一直在循环进行如上步骤。

任务队列的 JS 实现

我们选择使用数组来维护队列的执行顺序,按照“先进先出“的原则,依次从数组的第一个元素开始往后执行。

简易代码实现如下:

/** @format */

class TaskQueue {
    constructor() {
        this.queue = [];
        this.isRunning = false;
    }

    /**
     * @description 将任务添加至队列
     * @param {Promise} queueFunction
     * @returns {undefined}
     */
    addQueue(queueFunction) {
        this.queue.push(queueFunction);
        if (!this.isRunning) {
            this.processQueue();
        }
    }

    /**
     * @description 如果队列不为空,则开始处理队列中的任务,本次任务执行完毕后,立刻开始下一条任务的执行
     * @param {}
     */
    processQueue() {
        if (this.queue.length > 0) {
            this.isRunning = true;
            const queueFunction = this.queue.shift();
            queueFunction().finally(() => {
                this.processQueue();
            });
        } else {
            this.isRunning = false;
        }
    }
}

测试

我们使用如下代码来测试上述实现:

let taskQueue = new TaskQueue();

let f1 = function (name) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log(`我是 f1`, name);
            resolve();
        }, 3000);
    });
};

let f11 = async function () {
    await f1("    任务 1");
};

let f2 = function (name) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log(`我是 f2`, name);
            resolve();
        }, 2000);
    });
};

let f22 = async function () {
    await f2("    任务 2");
};

let f3 = function (name) {
    return new Promise((resolve) => {
        setTimeout(() => {
            console.log(`我是 f3`, name);
            resolve();
        }, 1000);
    });
};

let f33 = async function () {
    await f3("    任务 3");
};

taskQueue.addQueue(f11);
taskQueue.addQueue(f22);
taskQueue.addQueue(f33);

// 依次输出:
// 我是 f1     任务 1
// 我是 f2     任务 2
// 我是 f3     任务 3

如果不使用任务队列,上面的测试应该是按照 f1 -> f2 -> f3 的顺序执行,但是使用了任务队列之后,f1 -> f2 -> f3 的顺序执行被改变了,这是因为任务队列的执行顺序是按照添加的顺序来的,而不是按照执行顺序来的。

总结

任务队列的实现非常简单,但是使用起来却非常灵活,我们可以根据实际需求来决定任务队列的执行顺序,也可以根据实际需求来决定任务队列的执行时机。

本文算是抛砖引玉,介绍了简洁版的任务队列实现,如果大家有更好的想法和建议,都可以在评论区留言,一起讨论。

~

~ 本文完,感谢阅读!

~

标签:顺序,队列,JS,任务,resolve,let,执行
From: https://blog.51cto.com/bianchengsanmei/7558210

相关文章

  • js加密双重保障之sm2国密
    前言 最近看到一些项目里边有用到sm2/3/4国密加密算法,这里给大家简单介绍一下。知识科普SM2(国密算法)是一种非对称加密算法,由中国国家密码管理局(NCC)制定,并被广泛应用于中国的信息安全领域。它基于椭圆曲线密码学,主要用于数字签名和数据加密。以下是SM2国密算法的一些关键特点:安全性:S......
  • JS逆向
    场景:登录时账号或密码被加密而无法爆破或Fuzz的情况,如果是前端加密可以尝试js逆向,搭配phantomjs(JavaScriptAPI)和bp插件JSEncryptr进行爆破一、https://my.sto.cn/1.点击登录,可见发送了一个数据包LoginResult,地址是/Vip/LoginResult2.ctrl+shift+f全局查找/Vip/LoginRe......
  • 一些H5对接微信JSSDK的问题记录
    这里给大家分享我在实际生活中总结出来的一些知识,希望对大家有所帮助一.SDK引入这里提供两套引入流程,一套是vue2.0及其他h5项目,一套是vue3.0的引入流程不懂的也可以看我之前的一篇详细流程记录--微信调用jssdk全流程详解1.js引入直接在你的页面里引入js文件就行<scriptsr......
  • Swagger生产nodejs后台代码(nestia框架)
    Swagger文档生产nestia框架代码#SETUPGLOBALLYnpminstall-g@nestia/migrate#DOMIGRATEnpx@nestia/migrateswagger.jsonoutput_directoryNPM是一个Node包管理器,NPX是一个Node包执行器。npm查看全局安装的包npmls-g......
  • Windows 下更新 node.js
    一、node.js更新(一)查询node.js版本node-v(二)查询node.js安装位置wherenode(三)官网下载安装包https://nodejs.org/dist/下载对应版本的msi文件(四)安装到原位置,覆盖旧版本如:D:\ProgramFiles\nodejs\二、npm更新(一)查看版本npm-v(二)更新版本npmup......
  • Window计划任务调用exe程序时日志文件没有写出问题
    转自:https://blog.csdn.net/qq273766764/article/details/50729967/在之前写的exe程序中均有写文件日志操作,直接运行时是有日志文件的,但是配置到计划任务中就没有日志文件产生,程序的读写权限都已配置,但仍是没有日志文件之后百度了一下,原因是由于没有配置操作中的起始于选项,程......
  • js,格式化long类型日期封装
    /***扩展date函数*author:c3gen*/Date.prototype.format=function(format){varo={"M+":this.getMonth()+1,"d+":this.getDate(),"h+":this.getHours(),"m+":......
  • JS 对象(Object)和字符串(String)互转
    利用原生JSON对象,将对象转为字符串1.varjsObj={};2.jsObj.testArray=[1,2,3,4,5];3.jsObj.name='CSS3';4.jsObj.date='8May,2011';5.varstr=JSON.stringify(jsObj);6.alert(str);从JSON字符串转为对象1.varjsObj={};2.jsObj.......
  • js触发事件备忘
    一般事件事件浏览器支持描述onClick: 鼠标点击事件,多用在某个对象控制的范围内的鼠标点击onDblClick: 鼠标双击事件onMouseDown: 鼠标上的按钮被按下了onMouseUp: 鼠标按下后,松开时激发的事件onMouseOver: 当鼠标移动到某对象范围的上方时触发的事件onMouseMove:......
  • web开发:详细讲解jsp的内置对象
    1.request对象   客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。序号方法说明1objectgetAttribute(Stringname)返回指定属性的属性值2EnumerationgetAttributeNames()返回所有可用属性名的......