精华内容
下载资源
问答
  • nodejs事件队列

    2021-08-03 14:51:04
    Node里的事件队列和浏览器中的差异性还是比较大的,但是共同点就是宏任务和微任务的机制,是一样的,如图是关于node的宏任务与微任务分类。 nexttick会在node的每一次事件开启时最先执行(微任务最高优先级)。 而...

    Node里的事件队列和浏览器中的差异性还是比较大的,但是共同点就是宏任务和微任务的机制,是一样的,如图是关于node的宏任务与微任务分类。
    在这里插入图片描述
    nexttick会在node的每一次事件开启时最先执行(微任务最高优先级)。

    而关于node事件队列可分为如下6个阶段:
    在这里插入图片描述
    1.timers 阶段:这个阶段执行timer(setTimeout、setInterval)的回调
    2.I/O callbacks 阶段:执行一些系统调用错误,比如网络通信的错误回调
    3.idle, prepare 阶段:仅node内部使用
    4.poll 阶段:获取新的I/O事件, 适当的条件下node将阻塞在这里
    5.check 阶段:执行 setImmediate() 的回调
    6.close callbacks 阶段:执行 socket 的 close 事件回调

    我们重点看timers、poll、check这3个阶段就好,因为日常开发中的绝大部分异步任务都是在这3个阶段处理的。

    timers 阶段

    timers 是事件循环的第一个阶段,Node 会去检查有无已过期的timer,如果有则把它的回调压入timer的任务队列中等待执行,事实上,Node 并不能保证timer在预设时间到了就会立即执行,因为Node对timer的过期检查不一定靠谱,它会受机器上其它运行程序影响,或者那个时间点主线程不空闲。比如下面的代码,setTimeout() 和 setImmediate() 的执行顺序是不确定的。

    setTimeout(() => {
      console.log('timeout')
    }, 0)
    
    setImmediate(() => {
      console.log('immediate')
    })
    

    如上段代码是个大坑,node无法确定每次事件队列建立完毕的具体时间,可能这一次是5ms(timer被压入栈,在第二轮才会执行),下一次是1ms(timer在第一轮就被捕获执行了)。因此输出结果顺序不确定,这也是具体原因,而当嵌套一个异步的操作把他们包裹起来,就会100%保证immediate先执行。

    fs.readFile('./index.html',(err,result)=>{
    	setTimeout(() => {
    	  console.log('timeout')
    	}, 0)
    	
    	setImmediate(() => {
    	  console.log('immediate')
    	})
    })
    

    这是因为由于在第一轮未捕捉在timer,所以直接到了poll阶段进行io的回调捕捉,当io结束后进入check阶段,就会执行immediate,而timeout会在第二轮最开始的timer执行。

    poll 阶段

    poll 阶段主要有2个功能:
    1.处理 poll 队列的事件
    2.当有已超时的 timer,执行它的回调函数

    even loop将同步执行poll队列里的回调,直到队列为空或执行的回调达到系统上限(上限具体多少未详),接下来even loop会去检查有无预设的setImmediate(),分两种情况:

    1.若有预设的setImmediate(), event loop将结束poll阶段进入check阶段,并执行check阶段的任务队列
    2.若没有预设的setImmediate(),event loop将阻塞在该阶段等待

    注意一个细节,没有setImmediate()会导致event loop阻塞在poll阶段,这样之前设置的timer岂不是执行不了了?所以咧,在poll阶段event loop会有一个检查机制,检查timer队列是否为空,如果timer队列非空,event loop就开始下一轮事件循环,即重新进入到timer阶段。

    check 阶段

    setImmediate()的回调会被加入check队列中, 从event loop的阶段图可以知道,check阶段的执行顺序在poll阶段之后。

    小结
    node中每一轮大的事件循环中划分出了六个场景,每个场景需要按顺序执行,比浏览器会更加细化,并且在每一个阶段都会进行宏任务和微任务的处理,这是比较特殊的一点。

    1.Node.js 的事件循环分为6个阶段
    2.浏览器和Node 环境下,microtask 任务队列的执行时机不同
    Node.js中,microtask 在事件循环的各个阶段之间执行
    浏览器端,microtask 在事件循环的 macrotask 执行完之后执行
    3.递归的调用process.nextTick()会导致I/O starving,官方推荐使用setImmediate()
    4.每个事件阶段nexttick在微任务中的优先级是最高的。

    展开全文
  • NodeJS Redis 队列 开发中 Alpha 版本计划于 2015 年 5 月发布 去做 要求 NodeJS v0.10.x 或更高版本 新产品管理 Redis v2.8.x 或更高版本 见./package.json 安装 提供的源代码或通过 NPM 安装模块: $ npm ...
  • nodejs实现队列

    千次阅读 2017-11-13 01:46:40
    //队列push频率高,pop频率低 if (( this .filelist.length- this .top) > MAXLEN) { this .filelist= this .filelist.splice( this .top,MAXLEN- 700 ); this .top= 0 ; } } } module.exports= new ...
    "use strict"
    const MAXLEN=2000;
    class Queue {
        constructor() {
            this.filelist=[];
            this.top=0;
        }
        Push(path){
            this.filelist.push(path);
        }
        Pop() {
            if (this.top < this.filelist.length) {
                if (this.top > 32) {
                    this.filelist=this.filelist.splice(this.top,this.filelist.length-this.top);
                    this.top=0;
                }
                this.top+=1;
                return this.filelist[this.top-1]
            } else {
                return null;
            }
            this.Shuff();
        }
        Length(){
            return (this.filelist.length-this.top);
        }
        Shuff(){
            //队列push频率高,pop频率低
            if ((this.filelist.length-this.top) > MAXLEN) {
                this.filelist=this.filelist.splice(this.top,MAXLEN-700);
                this.top=0;
            }
        }
    }
    
    module.exports=new Queue();
    展开全文
  • nodejs操作消息队列RabbitMQ

    千次阅读 2019-06-21 21:59:00
    消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已。 其主要用途:不同进程Process/线程Thread之间通信。 为什么会产生消息队列?有...

    安装RabbitMQ https://blog.csdn.net/qq_35014708/article/details/93232033

    一. 什么是消息队列

    消息队列(Message Queue,简称MQ),从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已。
    其主要用途:不同进程Process/线程Thread之间通信。

    为什么会产生消息队列?有几个原因:

    不同进程(process)之间传递消息时,两个进程之间耦合程度过高,改动一个进程,引发必须修改另一个进程,为了隔离这两个进程,在两进程间抽离出一层(一个模块),所有两进程之间传递的消息,都必须通过消息队列来传递,单独修改某一个进程,不会影响另一个;

    不同进程(process)之间传递消息时,为了实现标准化,将消息的格式规范化了,并且,某一个进程接受的消息太多,一下子无法处理完,并且也有先后顺序,必须对收到的消息进行排队,因此诞生了事实上的消息队列;

    二. 常用的消息队列

    RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq

    三. 使用场景

    • 异步处理

    • 应用解耦

    • 流量削峰

    四 使用amqplib操作RabbitMQ

    安装 amqplib

    npm install amqplib

    生产者:

    let amqp = require('amqplib');
    
    class RabbitMQ {
        constructor() {
            this.hosts = [];
            this.index = 0;
            this.length = this.hosts.length;
            this.open = amqp.connect(this.hosts[this.index]);
        }
        sendQueueMsg(queueName, msg, errCallBack) {
            let self = this;
    
            self.open
                .then(function (conn) {
                    return conn.createChannel();
                })
                .then(function (channel) {
                    return channel.assertQueue(queueName).then(function (ok) {
                        return channel.sendToQueue(queueName, new Buffer(msg), {
                            persistent: true
                        });
                    })
                        .then(function (data) {
                            if (data) {
                                errCallBack && errCallBack("success");
                                channel.close();
                            }
                        })
                        .catch(function () {
                            setTimeout(() => {
                                if (channel) {
                                    channel.close();
                                }
                            }, 500)
                        });
                })
                .catch(function () {
                    let num = self.index++;
    
                    if (num <= self.length - 1) {
                        self.open = amqp.connect(self.hosts[num]);
                    } else {
                        self.index == 0;
                    }
                });
        }
    }
    
    let mq = new RabbitMQ();
    mq.sendQueueMsg('testQueue', '123', (error) => {
        console.log(error)
    })

    消费者

    let amqp = require('amqplib');
    
    class RabbitMQ {
        constructor() {
            this.hosts = [];
            this.index = 0;
            this.length = this.hosts.length;
            this.open = amqp.connect(this.hosts[this.index]);
        }
    
        receiveQueueMsg(queueName, receiveCallBack, errCallBack) {
            let self = this;
    
            self.open
                .then(function (conn) {
                    return conn.createChannel();
                })
                .then(function (channel) {
                    return channel.assertQueue(queueName)
                        .then(function (ok) {
                            return channel.consume(queueName, function (msg) {
                                if (msg !== null) {
                                    let data = msg.content.toString();
                                    channel.ack(msg);
                                    receiveCallBack && receiveCallBack(data);
                                }
                            })
                                .finally(function () {
                                    setTimeout(() => {
                                        if (channel) {
                                            channel.close();
                                        }
                                    }, 500)
                                });
                        })
                })
                .catch(function () {
                    let num = self.index++;
                    if (num <= self.length - 1) {
                        self.open = amqp.connect(self.hosts[num]);
                    } else {
                        self.index = 0;
                        self.open = amqp.connect(self.hosts[0]);
                    }
                });
        }
    }
    
    let mq = new RabbitMQ();
    mq.receiveQueueMsg('testQueue',(msg) =>
    {
        console.log(msg)//123
    })
    

    打开mq后台 http://127.0.0.1:15672/ 看到新增队列,接受一条消息

     

    当运行消费者代码时输入 123,消息队列消息为0

    展开全文
  • 消息队列 带有aws sqs的nodejs中的消息队列
  • 节点锁定作业 具有调度和锁定功能的 NodeJS 作业队列
  • redis+nodejs实现队列的思路

    千次阅读 2013-08-03 21:51:45
    redis里面天然的list链表非常适合做队列,下面看一个简单的nodejs+redis队列的实现过程  我们需要两个页面 一个index.ejs和一个pop.ejs分别来查看入队和出队的情况 index.ejs代码如下: push页面 ...
    redis里面天然的list链表非常适合做队列,下面看一个简单的nodejs+redis队列的实现过程 
    


       我们需要两个页面 一个index.ejs和一个pop.ejs分别来查看入队和出队的情况


    index.ejs代码如下:

    <!doctype html>
    <html>
        <head>
            <title>push页面</title>
            <script src="/socket.io/socket.io.js"></script>
            <script>
                window.onload = function(){    
                    var iosocket = io.connect();    
                    iosocket.on('connect',function(){
                        iosocket.on('push',function(push){
                            var ul = document.getElementsByTagName('ul')[0];
                            var li = document.createElement('li');
                            li.innerHTML = push;
                            ul.appendChild(li);
                        })
                    })
                }
            </script>
        </head>
        <body>
            <ul>
            </ul>
        </body>
    </hmtl>



    pop.ejs代码如下:

    <!doctype html>
    <html>
        <head>
            <title>pop页面</title>
            <script src="/socket.io/socket.io.js"></script>
            <script>
                window.onload = function(){    
                    var iosocket = io.connect();    
                    iosocket.on('connect',function(){
                        iosocket.on('pop',function(pop){
                            var ul = document.getElementsByTagName('ul')[0];
                            var li = document.createElement('li');
                            li.innerHTML = pop;
                            ul.appendChild(li);
                        })
                    })
                }
            </script>
        </head>
        <body>
            <ul>
            </ul>
        </body>
    </hmtl>



    下面看下路由方面的控制:

    exports.index = function(req, res){
      var redis = require('redis').createClient();
      redis.auth('chenqiguo');
        var date = 'A_'+(new Date()).valueOf();
        redis.lpush('list1',date);
        iosocket.on('connection',function(socket){
           socket.emit('push',date);
        })
        res.render('index', { title: 'pop',push:date});
     
      
     
    };
    
    exports.pop = function(req,res){
      var redis = require('redis').createClient();
      redis.auth('chenqiguo');
        redis.rpop('list1',function(err,result){
            iosocket.on('connection',function(socket){
                socket.emit('pop',result);
            })
            res.render('pop', { title: 'pop' });
        });
    }


    这样一个简单的队列实现思路就出来了,记住一定要在同一个list上面操作 
    展开全文
  • 消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ 中取消息而不管是谁发布的。...
  • 具有队列支持的基于承诺的集体服务包装器,完全可以在浏览器和/或Node.js环境中使用 有时,您需要从共享管道传递服务功能,并对所有功能调用某些操作。 或者,您可能想将所有服务添加到支持并行和暂挂任务的队列中。...
  • nodejs是一个基于google v8+javascript的服务端编程框架。对于搞云计算,用nj来做系统管理Web站点是非常合适的。理由是: a.足够简单。 b.足够快。 c.足够小巧。 d.前后端一致性。 下面是安装步骤: 1...
  • nodejs一个函数实现消息队列中间件

    千次阅读 2018-02-07 13:09:15
    消息队列中间件(Message Queue)相信大家不会陌生,如Kafka、RabbitMQ、RocketMQ等,已经非常成熟,在大大小小的公司和项目中也已经广泛使用。 有些项目中,如果是只使用初步的消息队列功能(比如少量客户端和简单的...
  • Nodejs 数组的队列以及forEach应用

    千次阅读 2017-11-06 18:23:17
    Nodejs 数组的队列以及forEach应用本文主要记录了在Nodejs开发过程中遇到过的由数组特性引起的问题及解决方式,以及对数组的灵活应用。 本文代码测试结果均基于node v6.9.5Nodejs 数组的队列以及forEach应用 数组与...
  • 为什么写这篇文章现在的面试要求越来越高了,打开看了看几个 BOSS 招聘 Node.js 全栈开发的,其中都有一条“了解 消息队列,并在项目中应用过”,呜呜呜后端开发者应该都知道消息队列...
  • 注意:nodejs >= 7.6.0 文档 笔记 Http 消费者只支持定时器 msg(少于 3 天),无论 msg 是从 http 还是 tcp 协议产生的。 仅在特殊服务器集群中支持订购。 样本(github) 示例(code.aliyun.com) 发布消息 ...
  • 查阅资料,使用redis实现消息队列主要有两种方法 - 发布订阅模式 - 生产消费模式 这里主要说使用nodejs+redis来实现生产消费模式2、代码实现:生产者实现代码redisCli.lpush('MSGQ', JSON.stringify(message), ...
  • nodeMQ 是基于Nodejs 和Redis 开发的消息队列系统,目前仅仅是beta版本。 支持简单的put get操作,采用http协议访问。项目地址:https://github.com/lnmp/nodemq Redis client 采用的是 ...
  • MQ全称为Message Queue,消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列消息(针对应用程序的数据)来通信,而无需专用连接来链接它们>。消 息传递指的是程序之间通过在消息中...
  • 消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保...消息队列的使用场景异步处理应用解耦流量削峰使用nodejs+UDP实现一个简单的消息队列const udpClient = require('dgr...
  • 目前在生产环境,使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ等。 转载于:https://www.cnb...
  • mq.sendQueueMsg("queue1", "这是一个队列消息", function (err) { console.log(err) }) }, 5000) setInterval(function () { mq.receiveQueueMsg("queue1", function (msg) { console.log(msg) }, function ...
  • 说到nodejs的事件队列

    千次阅读 2012-12-08 13:19:49
    事件队列,将任务按序执行。  应用场景:最经典的是WEB中的事件编程,如下 function event1(){ // do event 1 } function event2(){ // do event 2 } Click Me! 在上面的代码中 为button控件的onclick...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,997
精华内容 4,398
关键字:

nodejs消息队列