NodeJS中的异步I/O、事件驱动
nodejs的主要特点是单线程、异步I/O、事件驱动。让我们先大概了解一下这些名词的意思。
单线程
单线程是任务按照顺序执行的,并且每次只执行一个任务,只有前面的任务执行完成以后,后面的任务才执行。在JS引擎中负责解释和执行JavaScript代码的线程只有一个,即主线程。但实际上还存在其他的线程。例如处理AJAX请求的线程、处理DOM事件的线程、定时器线程、读写文件的线程等。这些线程可能存在与JS引擎之内,也可能存在与JS引擎之外,这些线程为工作线程。
同步和异步
同步:执行任务时,后面的任务需要等到前一个任务执行结束才可以执行,任务执行的顺序和任务排列的顺序是相同的
异步:每个任务有一个或多个callback,前一个任务执行完成以后不是执行后一个任务,而是执行回调函数。后一个任务也不是等到前一个任务执行完成后再执行,程序的执行顺序与任务的排列顺序不一致
现在我们看一下异步调用的基本过程
var fs = require('fs');
console.log('begin');
setTimeout(function(){
console.log('timeout1');
},100) fs.readFile('test.txt',function(err,data){
console.log(data);
console.log(data.toString());
}) setTimeout(function(){
console.log('timeout2');
},100) console.log('end');
分析一下结果:
由于NodeJS是单线程运行的,首先会顺序执行js文件中的代码,此时事件循环是暂停的。setTimeout和读文件的操作都是异步操作,异步函数会在工作线程执行,当异步函数执行完成以后,将回调函数放入消息队列。当js文件执行完成以后,事件循环开始执行,并从消息队列中取出消息,开始执行回调函数。
而整个异步函数的执行过程如下:
主线程发起一个异步请求,相应的工作线程接收请求并告知主线程已收到(异步函数返回);主线程可以继续执行后面的代码,同时工作线程执行异步任务;工作线程完成工作以后,通知主线程;主线程收到通知后,执行一定的动作(调用回调)
事件驱动
事件驱动编程主要思想是通过事件或状态的变化来进行应用程序的流程控制,一般通过事件监听完成,一旦事件被检测到,则调用相应的回调函数。事件驱动主要执行过程是当进来的一个新的请求的时候,请求将会被压入队列中,然后通过一个循环来检测队列中的事件状态变化,如果检测到有状态变化的事件,那么就执行该事件对应的处理代码,一般都是回调函数。
线程驱动是当收到一个请求的时候,将会为该请求开一个新的线程来处理请求。而线程主要是由线程池来管理的。当线程池中有空闲的线程,会从线程池中拿取线程来处理,如果线程池中没有空闲的线程,新来的请求将会进入队列排队,直到线程池中空闲线程
异步I/O
nodejs是单线程运行的,通过一个事件循环来循环取出消息队列中的消息进行处理,处理过程基本上就是去调用该消息对应的回调函数。消息队列就是当一个事件状态发生变化时,就将一个消息压入队列中
NodeJS的事件循环模型一般要注意下面几点:
- 因为是单线程的,所以当顺序执行js文件中的代码的时候,事件循环是被暂停的
- 当JS文件执行完以后,事件循环开始运行,并从消息队列中取出消息,开始执行回调函数
- 因为是单线程的,所以当回调函数被执行的时候,事件循环是被暂停的
- 当涉及到I/O的时候,nodejs会开一个独立的线程来进行异步I/O操作,操作结果以后将消息压入消息队列
内部实现
在NodeJS中整个异步I/O模型的基本要素是事件循环、观察者、请求对象和I/O线程池。整个异步I/O的流程图如下:
整个实现过程大概更可以描述为:发起异步请求之后将请求进行封装,封装为请求对象,对请求对象设置参数和回调函数并将请求对象放入线程池,线程池中检查是否有可用线程,当线程可用时执行请求对象的I/O操作,并将执行完成的结果放入请求对象中,通知IOCP调用完成并获取完成的I/O交给I/O观察者。
在libuv中创建主循环开始事件循环,主循环从I/O观察者中取出可用的请求对象,在请求对象中取出回调函数和I/O结果并调用回调函数
https://segmentfault.com/a/1190000003751278
转载至 :http://blog.csdn.net/charlene0824/article/details/51711154
NodeJS中的异步I/O、事件驱动的更多相关文章
- nodejs 中的异步之殇
nodejs 中的异步之殇 终于再次回到 nodejs 异步中,以前我以为异步在我写的文章中,已经写完了,现在才发现,还是有很多的地方没有想清楚,下面来一一说明. 模块同步与连接异步 大家应该,经常使 ...
- 如何优雅的处理Nodejs中的异步回调
前言 Nodejs最大的亮点就在于事件驱动, 非阻塞I/O 模型,这使得Nodejs具有很强的并发处理能力,非常适合编写网络应用.在Nodejs中大部分的I/O操作几乎都是异步的,也就是我们处理I/O ...
- 深入理解nodejs中的异步编程
目录 简介 同步异步和阻塞非阻塞 javascript中的回调 回调函数的错误处理 回调地狱 ES6中的Promise 什么是Promise Promise的特点 Promise的优点 Promise ...
- Nodejs中使用异步流程控制Async
首先,我们都知道,Node基于事件驱动的异步I/O架构,所谓异步就是非阻塞,说白了就是一个事件执行了,我不必等待它执行完成后我才能执行下一个事件.所以在Node环境中的模块基本都是异步的,上一篇说到我 ...
- NodeJS中常见异步接口定义(get、post、jsonp)
越来越多的人在使用nodeJS,作为一门服务端语言,我们不可避免的要写异步接口(ajax和jsonp).再次强调ajax和jsonp是两个概念,但是由于jquery的封装,使这两种异步接口的调用方式, ...
- nodejs中的异步回调机制
1.再次clear Timer定时器的作用 setTimeOut绝非是传统意义上的“sleep”功能,它做不到让主线程“熄火”指定时间,它是用来指定:某个回调在固定时间后插入执行栈!(实际执行时间略长 ...
- nodejs中的异步流程序控制nsync
异步编程是指由于异步I/O等因素,无法同步获得执行结果时, 在回调函数中进行下一步操作的代码编写风格,常见的如setTimeout函数.ajax请求等等 http://cnodejs.org/topi ...
- nodejs中异步
nodejs中的异步 1 nodejs 中的异步存在吗? 现在有点 javascript 基础的人都在听说过 nodejs ,而只要与 javascript 打交到人都会用或者是将要使用 nodejs ...
- nodejs中的子进程,深入解析child_process模块和cluster模块
Node.js的进程管理 node遵循的是单线程单进程的模式,node的单线程是指js的引擎只有一个实例,且在nodejs的主线程中执行,同时node以事件驱动的方式处理IO等异步操作.node的 ...
随机推荐
- 写个shell脚本
以前更新网站程序都是手动噼里啪啦敲代码,即麻烦又慢,还神经紧张.终于忍不住写个shell脚本. cd /usr/local/tomcat7/apache-tomcat-9.0.0.M4/ bin/ ...
- Subversion Edge
http://www.collab.net/downloads/subversion#tab-1
- jQuery队列操作
jQuery.queue 1."fx"是什么? 队列动画的默认名称 队列的名字为type + "queue",默认是"fxqueue" 2. ...
- java多线程 生产者消费者模式
package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...
- Android 隐藏关闭软键盘
直接复制代码就可以用 InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVI ...
- 基于ThinkPHP开发的PHPExcel导入
首先,我们还是要导入PHPExcel类文件...至于怎么导入.可以参考我写的导出的那篇文章(http://www.cnblogs.com/hopelooking/p/6230303.html) 但是我 ...
- 分享一个很早之前写的小工具DtSpyPlus
几年前写的一个获取windows窗体基本信息和屏幕取色的小工具 ,一直在用. 下载地址 http://files.cnblogs.com/dint/SpyPlus.zip
- Selenium的PO模式(Page Object Model)|(Selenium Webdriver For Python)
研究Selenium + python 自动化测试有近两个月了,不能说非常熟练,起码对selenium自动化的执行有了深入的认识. 从最初无结构的代码,到类的使用,方法封装,从原始函数 ...
- Mybatis-Spring集成
MyBatis-Spring用来将MyBatis无缝整合到Spring中.使用这个类库中的类, Spring将会加载必要的MyBatis工厂类和Session类. 这个类库也提供一个简单的方式来注入 ...
- ubuntu各种应用安装
微信安装,编译包下载,双击electronic-wechat就能用了,记得lock在launcher上 https://github.com/geeeeeeeeek/electronic-wechat ...