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的 ...
随机推荐
- Linux 下 PHP 扩展 cURL 编译安装
下载 cURL http://pan.baidu.com/s/1hqrHWkG (curl-7.39.0.tar.gz) 3.98MB 解压: tar zxvf curl-7.39.0.tar.gz ...
- python 图片爬虫
#!/usr/bin/env python #coding:utf-8 import urllib import re def GetHtml(url): """获取HT ...
- ios 使用AFN上传图片到服务器
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; manager.responseSe ...
- 基于ThinkPHP开发的PHPExcel导出
首先我们需要去PHPExcel官网下载开源包 下载好了以后只需要把里面的classes文件夹解压出来就可以用了! 在ThinkPHP中,文件的命名空间还是很重要的,我试着按照其他的第三方命名写name ...
- EBS learning history (to know about the environment)
prcsgidb1: /u01/Stage/database C:\Users\alley_li>ping prcsgidb1 Pinging prcsgidb1.ad.infosys.com ...
- [已解决] github merge指定commit
比如说有两个branch,分别是master和m1,我们在m1上修改的bug怎么merge到master上呢, 怎么merge我不知道,但是有另外一个命令可以做到,比如m1做commit,sha-1为 ...
- C# ASP.NET 读取EXCEL 单元格 读取 空值 不显示
跟大家分享一下,[摘自]:http://blog.csdn.net/li185416672/article/details/8213729 读取excel时,某些单元格为空值 原来如此: 当我们用ol ...
- java udp与tcp
一:基础 NET基本对象java.net.InetAddress类的使用 IP地址是IP使用的32位(IPv4)或者128位(IPv6)位无符号数字,它是传输层协议TCP,UDP的基础.InetAd ...
- angular源码阅读,依赖注入的原理:injector,provider,module之间的关系。
最开始使用angular的时候,总是觉得它的依赖注入方式非常神奇. 如果你跳槽的时候对新公司说,我曾经使用过angular,那他们肯定会问你angular的依赖注入原理是什么? 这篇博客其实是angu ...
- 从零开始学习Android(一)Android环境的搭建
好久没有开始写博客了,最近开始学习Android,所以想把学习的笔记都一一记录下来.一来是方便自己以后资料的查询,其次也是给Android新手朋友进行学习使用,再次也希 望得到高手的指点.废话少说,我 ...