引言

node作为服务器的优势就在于适合处理高并发的请求,对于web网站后台这种I/O密集型的后台尤其有优势,其核心就在于node是一个异步非阻塞模型。关于异步,同步,阻塞,非阻塞这些概念,本文不做讨论。

node的单线程模型

js作为单线程语言,有自己的一套运行机制

同步任务运行在主线程上,异步的所有任务都会在另一个队列中等待执行,一旦同步任务执行完毕开始执行异步队列中的任务,此时可以认为将第一个异步队列中的任务移到主线程,一旦再产生异步操作,就会继续往异步队列中添加,以此循环。这就是为什么promise,setTimeout,setInterval,process.nextTick,setImmediate,ajax请求,看起来虽然位于代码的上面部分却没有被按顺序执行。
看一下node的eventloop的机制,也就是node实现异步的架构。

主要的不同点是用LIBUV去将队列中的任务形成一个eventloop,作为下一个循环需要执行的工作。

观察者模式的体现

个人一直认为js的异步回调是一种观察者模式的体现,订阅/发布,网上的说法是有三种观察者

idle观察者:顾名思义,就是早已等在那里的观察者,以后会说到的process.nextTick就属于这类

I/O观察者:顾名思义,就是I/O相关观察者,也就是I/O的回调事件,如网络,文件,数据库I/O等

check观察者:顾名思义,就是需要检查的观察者,后面会说到的setTimeout/setInterval就属于这类

优先级idle观察者>I/O观察者>check观察者

详细链接

但是个人看法setTimeout()和setInterval()可以归为一类观察者,算是timer观察者,setImmediate()是check观察者,至于原因后面回说明

以下是自己对setTimeout(),setImmediate()和process.nextTick()的比较

首先所有讨论均是建立在node的基础上,三个函数也都只比较分析node 中情况,摘自node文档

setTimeout()

callback <Function> The function to call when the timer elapses.
delay <number> The number of milliseconds to wait before calling the callback.

Schedules execution of a one-time callback after delay milliseconds. Returns a Timeout for use with clearTimeout().

The callback will likely not be invoked in precisely delay milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified.

这里明确了两点,一个是settimeout的实际执行时间必然晚于设置时间,作精确定时器根本就是违背他的设计意愿的,另外一点就是他的函数回调是timer观察的。

setImmediate()

callback <Function> The function to call at the end of this turn of the Node.js Event Loop
...args <any> Optional arguments to pass when the callback is called.

Schedules the "immediate" execution of the callback after I/O events' callbacks. Returns an Immediate for use with clearImmediate().
When multiple calls to setImmediate() are made, the callback functions are queued for execution in the order in which they are created. The entire callback queue is processed every event loop iteration. If an immediate timer is queued from inside an executing callback, that timer will not be triggered until the next event loop iteration.

核心,回调会被立刻放在eventLoop的末尾

process.nextTick()

callback <Function>
...args <any> Additional arguments to pass when invoking the callback

he process.nextTick() method adds the callback to the "next tick queue". Once the current turn of the event loop turn runs to completion, all callbacks currently in the next tick queue will be called.
This is not a simple alias to setTimeout(fn, 0). It is much more efficient. It runs before any additional I/O events (including timers) fire in subsequent ticks of the event loop.

文档中自己就提到了process.nextTick()并非 setTimeout(fn, 0),他更有效率,并且执行的序列必在下次所有的event loop的最前列。

比较

之后在node文档中有一个比较细致的比较,链接

比较这三个函数,先说process.nextTick(),文档中说了process.nextTick() is not technically part of the event loop,现在很明确了process.nextTick()并不在event loop里,他回调的执行是在事件等待队列之外的,算是优先级最高的插队人员,那它作为最优先执行回调的就没有疑问了,实际的用处就是有一些必须最优先执行的回调,比如网络服务端中,端口的监听应该必须早于其他事件的回调。

setImmediate() vs setTimeout()

这个可能是网上说法最不统一的地方了,说谁先执行的都有,先测了下面的代码

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

结果还真的是随机的,这么不严谨?其实官方对这个是有解释的

The order in which the timers are executed will vary depending on the context in which they are called. If both are called from within the main module, then timing will be bound by the performance of the process (which can be impacted by other applications running on the machine).
However, if you move the two calls within an I/O cycle, the immediate callback is always executed first:

这个教育了我,真理是有范围的,所谓普遍真理是形而上学。所以说setImmediate() vs setTimeout()谁快不能简单的说,必须先讨论使用的地方。

上面有提到setTimeout(fn, 0)效率不高,至于为什么,暂时参照国内普遍的说法 该函数的事件控制,是被维护在红黑树上,那么为了每次去找超时的回调必然是logn的复杂度,而另外两个函数看起来都应该是1的复杂度

总结

  • 综上个人倾向于四种观察者的说法
  • 至于setImmediate() vs setTimeout() vs process.nextTick(),process.nextTick()最快,也有独特的应用场景。另外两个的调用时间需要判断是否都在主线程中被执行。
  • setTimeout(fn, 0)效率偏低。
  • tip:node官方建议使用setimmediate(),因为至少应用的范围就可以到浏览器端了。

node异步非阻塞的杂谈相关推荐

  1. Node.js:海量数据大行其道的今天 node.js 在IO方面如何异步非阻塞

    以其高性能,异步IO著称,当然node.js 在 stream 上的异步也非常到位. 我们一般理解的异步请求是这样的: 同时处理多件件事件 A,B,C,D,E,F,G .... 如果用.net语言去处 ...

  2. 处理大并发之一 对异步非阻塞的理解

    处理大并发之一 对异步非阻塞的理解 在研究nginx和node.js的时候常会遇到异步.非阻塞等,之前自己也经常使用epoll,对其同步与阻塞,异步与非阻塞有了一定的认识,现对参考资料总结下. 首先讨 ...

  3. NodeJs 异步非阻塞

    一般来说,高并发的解决方案就是提供多线程模型,服务器为每个客户端请求分配一个线程,使用同步 I/O,系统通过线程切换来弥补同步 I/O 调用的时间开销.比如 Apache 就是这种策略,由于 I/O ...

  4. 异步就是异步,根本就没有 异步非阻塞IO这个说法。阻塞 非阻塞,同步I/O 异步I/O 的区别

    先给大家安利一下这个 https://www.ibm.com/developerworks/cn/linux/l-async/ 里面关于 异步非阻塞IO 是错的. 异步就是异步,别扯 异步阻塞 异步非 ...

  5. 同步阻塞与异步非阻塞

    syncBlocking & asyncNonblocking 转载:https://www.zhihu.com/question/19732473/answer/23434554 作者:严肃 ...

  6. 线程同步 阻塞 异步 非阻塞(转)

    同步:函数没有执行完不返回,线程被挂起 阻塞:没有收完数据函数不返回,线程也被挂起 异步:函数立即返回,通过事件或是信号通知调用者 非阻塞:函数立即返回,通过select通知调用者 这样看来异步和非阻 ...

  7. python3 异步 非阻塞 IO多路复用 select poll epoll 使用

    有许多封装好的异步非阻塞IO多路复用框架,底层在linux基于最新的epoll实现,为了更好的使用,了解其底层原理还是有必要的. 下面记录下分别基于Select/Poll/Epoll的echo ser ...

  8. 真正的 Tornado 异步非阻塞

    其中 Tornado 的定义是 Web 框架和异步网络库,其中他具备有异步非阻塞能力,能解决他两个框架请求阻塞的问题,在需要并发能力时候就应该使用 Tornado. 但是在实际使用过程中很容易把 To ...

  9. 同步阻塞,同步非阻塞,异步阻塞,异步非阻塞IO

    在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操作. 在比较这两个模式之前,我们首先的搞明白 ...

最新文章

  1. 详解数组中的reduce方法
  2. [zz]用U盘装win7/XP系统的操作[图解]
  3. pycharm 如何通过VCS快速提交代码?
  4. 腾讯应用宝采集数据分析
  5. java多线程w3c_多线程
  6. Elastic-job使用及原理
  7. 计算机网络学习笔记-01-概念,组成,功能,分类
  8. 斯坦福 CS228 概率图模型中文讲义 一、引言
  9. html特殊字符转义倒三角,html,转义字符对照表,部分x
  10. c语言饭卡管理系统_c语言饭卡管理系统课程设计报告.pdf
  11. 【2022年更新】手把手教你去除 WinRAR 的弹窗广告
  12. 2小时部署实时反欺诈深度学习模型 —— IBM主机机器学习平台社区版简介
  13. 转载:矩阵L2,1范数及矩阵L2,p范数的求导
  14. 周志华----第5章神经网络(误差逆传播算法)
  15. Cyclone IV代FPGA的可编程逻辑资源
  16. (57)Linux驱动开发之三Linux字符设备驱动
  17. 《数字图像处理》第三章学习总结感悟1:灰度变换与空间滤波概念及常用灰度变换方法介绍
  18. 公共方法收集1:json_compare
  19. 有关冰川的小知识(1)
  20. MS SQL2016的安装

热门文章

  1. java dotnet core_在.NET Core 2.0中使用Omron库
  2. 南京信息工程大学c语言实验十报告,南京信息工程大学2014年C语言程序设计实验内容(全部).doc...
  3. python import re_Python标准库笔记(2) — re模块
  4. python测试开发django-44.xadmin上传图片和文件
  5. 设置一个双色球脚本(2)并带颜色输出
  6. Odoo访问权限(一)
  7. 高级软件工程第九次作业:东理三剑客团队作业-随笔4
  8. 字典常用的方法(内建函数)
  9. yii添加模型基础类
  10. 【转载】javascript下ie7,ie8的Date Bug的解决