JavaScript模拟队列的用法详解

 更新时间:2023年10月09日 08:25:24   作者:雾恋  
我原本以为JavaScript是不能写队列的,最近发现JavaScript是可以模拟队列的,并且花样还挺多,所以本文将给大家介绍JavaScript模拟队列的基础写法用法,需要的朋友可以参考下

场景

场景一:

有几百条数据需要传递给后端,但是后端每次最多只能接收10条数据

场景二:

在弹出第一个弹框并关闭后再弹第二个弹窗(或者广告一类的)

我想这些需求大家应该都了解过,或者遇到过,我们可能第一反应是通过定时器或者Promise来处理,现在我告诉你完全可以通过队列的方式来处理。我会写一些示例,如果运用到工作中请根据自己的需求进行修改即可。

说明

JavaScript 队列(Queue)是一种先进先出(FIFO)的数据结构,它用于存储按顺序排列的元素,并支持插入新元素和删除元素的操作。队列在计算机科学中有着广泛的应用,例如在操作系统中实现任务调度、在数据压缩中使用哈夫曼编码等。在JavaScript中,队列也常用于实现异步编程和控制流程。 JavaScript队列通常可以通过内置的Array对象实现,或者使用第三方库如queue-lib。Array对象提供了push()和shift()方法,可以模拟队列的入队和出队操作。

简单队列

我们从下面的模拟队列中可以看出,我们在执行的时候makeRequest(模拟请求)是依次开始执行,那么我们想同时执行多个请求呢?我们想间隔一段时间在发送请求呢?那我们接到看下面这个示例。

class RequestQueue {
    constructor() {
        this.queue = []; // 请求队列
        this.running = 0; // 当前正在运行的请求数量
    }
    // 将请求添加到队列中
    enqueue(request) {
        this.queue.push(request);
        this.run(); // 检查是否可以运行新的请求
    }
    // 检查并运行请求
    run() {
        if (this.running !== 0 || !this.queue.length) return;
        const request = this.queue.shift();
        this.execute(request);
        this.running++;
    }
    // 执行请求
    execute(request) {
        request().finally(() => {
            this.running--;
            if (this.queue.length <= 0) return;
            this.run();
        });
    }
}
// 模拟一个异步请求
function makeRequest(id) {
    return new Promise((resolve) => {
        console.log(`正在发送请求 ${id}`);
        setTimeout(() => {
            console.log(`请求 ${id} 完成`);
            resolve(id);
        }, 1000);
    })
}
// 创建请求队列并添加10个请求
const queue = new RequestQueue(1, 100);
for (let i = 1; i <= 10; i++) {
    queue.enqueue(async () => await makeRequest(i));
};

完整队列

我们从该队列中可以看出,我们可以去控制自己的并发量以及间隔时间了,那么我们在考虑下。如果队列执行完成了,我们怎么知道呢?等等。那我们就给他补充完全吧!(这只是我想到的,我没考虑到的你们也可以自己完善哈)

class RequestQueue {
    constructor(limit,delay) {
        this.limit = limit; // 最大并发请求数
        this.delay = delay; // 批次间隔时间(毫秒)
        this.queue = []; // 请求队列
        this.running = 0; // 当前正在运行的请求数量
    }
    // 将请求添加到队列中
    enqueue(request) {
        this.queue.push(request);
        this.run(); // 检查是否可以运行新的请求
    }
    // 检查并运行请求
    run() {
        while (this.running < this.limit && this.queue.length > 0) {
            const request = this.queue.shift();
            this.execute(request);
            this.running++;
        }
    }
    // 执行请求
    execute(request) {
        request().finally(() => {
            this.running--;
            if (this.queue.length > 0) {
                setTimeout(() => {
                this.run();
                }, this.delay);
            }
        });
    }
}
// 模拟一个异步请求
function makeRequest(id) {
    return new Promise((resolve) => {
        console.log(`发起请求 ${id}`);
        setTimeout(() => {
            console.log(`请求 ${id} 完成`);
            resolve(id);
        }, 100);
    })
}
// 创建请求队列并添加10,000个请求
const queue = new RequestQueue(5,1000);
for (let i = 1; i <= 20; i++) {
    queue.enqueue(async () => await makeRequest(i));
};

补充完整队列

我们在监听队列是否完成的时候注意一个事,就是Promise在返回的时候一定要在成功的时候才返回。至于原因,你们可以自己去尝试哈。

class RequestQueue {
    timer = null; // 定时器
    constructor(limit, delay) {
        this.limit = limit; // 最大并发请求数
        this.delay = delay; // 批次间隔时间(毫秒)
        this.queue = []; // 请求队列
        this.running = 0; // 当前正在运行的请求数量
    }
    // 将请求添加到队列中
    enqueue(request) {
        this.queue.push(request);
        this.run(); // 检查是否可以运行新的请求
    }
    // 检查并运行请求
    run() {
        while (this.running < this.limit && this.queue.length > 0) {
            const request = this.queue.shift();
            this.execute(request);
            this.running++;
        }
    }
    // 执行请求
    execute(request) {
        request().finally(() => {
            this.running--;
            if (this.queue.length > 0) {
                setTimeout(() => {
                    this.run();
                }, this.delay);
            }
        });
    }
    // 监听队列是否完成
    isQueueEmpty() {
        return new Promise((resolve, reject) => {
            this.timer = setInterval(() => {
                if (this.queue.length === 0 && this.running === 0) {
                    clearInterval(this.timer);
                    this.timer = null;
                    resolve(true);
                }
            }, 1000);
        })
    }
}
// 模拟一个异步请求
function makeRequest(id) {
    return new Promise((resolve) => {
        console.log(`发起请求 ${id}`);
        setTimeout(() => {
            console.log(`请求 ${id} 完成`);
            resolve(id);
        }, 100);
    })
}
// 创建请求队列并添加10,000个请求
const queue = new RequestQueue(5, 1000);
for (let i = 1; i <= 20; i++) {
    queue.enqueue(async () => await makeRequest(i));
};
// 执行完成返回ture
queue.isQueueEmpty().then(res=>{
    console.log(res);
})

总结

以上就是JavaScript模拟队列的基础写法用法,大家也可以根据你们的需要进行修改和完善。

到此这篇关于JavaScript模拟队列的用法详解的文章就介绍到这了,更多相关JavaScript模拟队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • js实现div色块碰撞

    js实现div色块碰撞

    这篇文章主要为大家详细介绍了js实现div色块碰撞,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • Json解析的方法小结

    Json解析的方法小结

    本文给大家带来了json解析方法小结的知识,非常不错,具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-06-06
  • JavaScript结合Bootstrap仿微信后台多图文界面管理

    JavaScript结合Bootstrap仿微信后台多图文界面管理

    这篇文章主要为大家详细介绍了js结合Bootstrap仿微信后台多图文界面管理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • BootStrap栅格系统、表单样式与按钮样式源码解析

    BootStrap栅格系统、表单样式与按钮样式源码解析

    这篇文章主要为大家详细解析了BootStrap栅格系统、表单样式与按钮样式源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • 快速排序 php与javascript的不同之处

    快速排序 php与javascript的不同之处

    告诉你一个排序算法,也许是最重要的是他们知道 - 快速排序,无论是在PHP和JavaScript实现的。虽然这两种语言之间的代码看起来相似,也有一些差异,这表明了语法知识的重要性!
    2011-02-02
  • JavaScript和CSS通过expression实现Table居中显示

    JavaScript和CSS通过expression实现Table居中显示

    如何将表格居中的显示使用一个叫expression的函数,多数的浏览器都支持这个函数,感兴趣的朋友可以看一下具体的实现哈
    2013-06-06
  • IE6-IE9不支持table.innerHTML的解决方法分享

    IE6-IE9不支持table.innerHTML的解决方法分享

    让ie6-ie9支持table.innerHTML,其实这里只是对table做了处理,对其他不支持的元素可以用类似的方案
    2012-09-09
  • 快速实现JS图片懒加载(可视区域加载)示例代码

    快速实现JS图片懒加载(可视区域加载)示例代码

    目前很多网站,在图片加载时均采用了一种名为懒加载的方式,具体表现为,当页面被请求时,只加载可视区域的图片,其它部分的图片则不加载,只有这些图片出现在可视区域时才会动态加载这些图片,下面本文就介绍了JS图片懒加载(可视区域加载)的实现方法,一起来看看吧。
    2017-01-01
  • js控制div层的叠加简单方法

    js控制div层的叠加简单方法

    下面小编就为大家带来一篇js控制div层的叠加简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-10-10
  • 开发跨浏览器javascript常见注意事项

    开发跨浏览器javascript常见注意事项

    对于javascript的开发人员来说,多浏览器的支持性,一直是个问题,每次都要经过测试,多个浏览器,才能使用下面一些常见的一些注意事项。
    2009-01-01

最新评论