有很多人对Node.js里process.nextTick()的用法感到不理解,下面我们就来看一下process.nextTick()到底是什么,该如何使用。

Node.js是单线程的,除了系统IO之外,在它的事件轮询过程中,同一时间只会处理一个事件。你可以把事件轮询想象成一个大的队列,在每个时间点上,系统只会处理一个事件。即使你的电脑有多个CPU核心,你也无法同时并行的处理多个事件。但也就是这种特性使得node.js适合处理I/O型的应用,不适合那种CPU运算型的应用。在每个I/O型的应用中,你只需要给每一个输入输出定义一个回调函数即可,他们会自动加入到事件轮询的处理队列里。当I/O操作完成后,这个回调函数会被触发。然后系统会继续处理其他的请求。

在这种处理模式下,process.nextTick()的意思就是定义出一个动作,并且让这个动作在下一个事件轮询的时间点上执行。我们来看一个例子。例子中有一个foo(),你想在下一个时间点上调用他,可以这么做:

运行上面的代码,你从下面终端打印的信息会看到,"bar"的输出在“foo”的前面。这就验证了上面的说法,foo()是在下一个时间点运行的。

你也可以使用setTimeout()函数来达到貌似同样的执行效果:

但在内部的处理机制上,process.nextTick()和setTimeout(fn, 0)是不同的,process.nextTick()不是一个单纯的延时,他有更多的 特性

更精确的说,process.nextTick()定义的调用会创建一个新的子堆栈。在当前的栈里,你可以执行任意多的操作。但一旦调用netxTick,函数就必须返回到父堆栈。然后事件轮询机制又重新等待处理新的事件,如果发现nextTick的调用,就会创建一个新的栈。

下面我们来看看,什么情况下使用process.nextTick():

在多个事件里交叉执行CPU运算密集型的任务:

在下面的例子里有一个compute(),我们希望这个函数尽可能持续的执行,来进行一些运算密集的任务。

但与此同时,我们还希望系统不要被这个函数堵塞住,还需要能响应处理别的事件。这个应用模式就像一个单线程的web服务server。在这里我们就可以使用process.nextTick()来交叉执行compute()和正常的事件响应。

在这种模式下,我们不需要递归的调用compute(),我们只需要在事件循环中使用process.nextTick()定义compute()在下一个时间点执行即可。在这个过程中,如果有新的http请求进来,事件循环机制会先处理新的请求,然后再调用compute()。反之,如果你把compute()放在一个递归调用里,那系统就会一直阻塞在compute()里,无法处理新的http请求了。你可以自己试试。

当然,我们无法通过process.nextTick()来获得多CPU下并行执行的真正好处,这只是模拟同一个应用在CPU上分段执行而已。

保持回调函数异步执行的原则

当你给一个函数定义一个回调函数时,你要确保这个回调是被异步执行的。下面我们看一个例子,例子中的回调违反了这一原则:

为什么这样不好呢?我们来看Node.js 文档里一段代码:

在上面的代码里,如果因为某种原因,net.connect()变成同步执行的了,回调函数就会被立刻执行,因此回调函数写到客户端的变量就永远不会被初始化了。

这种情况下我们就可以使用process.nextTick()把上面asyncFake()改成异步执行的:

用在事件触发过程中

来看一个例子,你想写一个库实现这样的功能:从源文件里读取数据,当读取完毕后,触发一个事件同时传递读取的数据。可能你会这样写:

下面是一段调用这个库的客户端程序,我们想在程序中监听这些事件:

但是上面的代码中,将永远接收不到“start”事件,因为在这个库实例化的时候,“start”事件会被立刻触发执行,但此时事件的回调函数还没有准备好,所以在客户端根本无法接收到这个事件。同样,我们可以用process.nextTick()来改写事件触发的过程,下面是一个正确的版本:

这就是process.nextTick()的基本用法.

本文地址:http://www.oschina.net/translate/understanding-process-next-tick

原文地址:http://howtonode.org/understanding-process-next-tick

其他资料

http://www.cnblogs.com/gaojun/p/4164864.html

理解 Node.js 里的 process.nextTick()的更多相关文章

  1. node.js(API解读) - process (http://snoopyxdy.blog.163.com/blog/static/60117440201192841649337/)

    node.js(API解读) - process 2011-10-28 17:05:34|  分类: node |  标签:nodejs  nodejsprocess  node.jsprocess  ...

  2. 深入理解 Node.js 进程与线程

    原文链接: https://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651557398&idx=1&sn=1fb991da ...

  3. 深入理解Node.js中的垃圾回收和内存泄漏的捕获

    深入理解Node.js中的垃圾回收和内存泄漏的捕获 文章来自:http://wwsun.github.io/posts/understanding-nodejs-gc.html Jan 5, 2016 ...

  4. 理解Node.js的事件轮询

    前言 总括 : 原文地址:理解Node.js的事件轮询 Node小应用:Node-sample 智者阅读群书,亦阅历人生 正文 Node.js的两个基本概念 Node.js的第一个基本概念就是I/O操 ...

  5. 方便大家学习的Node.js教程(一):理解Node.js

    理解Node.js 为了理解Node.js是如何工作的,首先你需要理解一些使得Javascript适用于服务器端开发的关键特性.Javascript是一门简单而又灵活的语言,这种灵活性让它能够经受住时 ...

  6. 如何理解Node.js和JavaScript的关系

    一.Javascript的引擎 浏览器一般有两个引擎,一个是Html引擎,一个是脚本引擎. JavaScript是一种脚本语言,最初用于浏览器的动态显示,方便操作页面数据和内容.但实际上,它也可以在浏 ...

  7. 转 node.js里面的http模块深入理解

    问题1:HTTP服务继承了TCP服务模型,是从connection为单位的服务到以request为单位的服务的封装,那么request事件何时触发? 注意:在开启keepalive后,一个TCP会话可 ...

  8. 理解Node.js(译文)

    前言 总括 :这篇文章十分生动形象的的介绍了Node,满足了读者想去了解Node的需求.作者是Node的第一批贡献者之一,德国前端大神.译者觉得作者的比喻很适合初学者理解Node,特此翻译. 译者 : ...

  9. 深度理解Node.js单线程模型

    Node.js采用 事件驱动 和 异步I/O 的方式,实现了一个单线程.高并发的运行时环境,而单线程就意味着同一时间只能做一件事,那么Node.js如何利用单线程来实现高并发和异步I/O?本文将围绕这 ...

随机推荐

  1. scikit-learn一般实例之一:绘制交叉验证预测

    本实例展示怎样使用cross_val_predict来可视化预测错误: # coding:utf-8 from pylab import * from sklearn import datasets ...

  2. 6.Configure Domain Classes(配置领域类)【EF Code-First 系列】

    在前面的部分中,我们学习了Code-First默认约定,Code-First使用默认的约定,根据你的领域类,然后生成概念模型. Code-First模式,发起了一种编程模式:约定大于配置.这也就是说, ...

  3. AngularJS------认识AngularJS

    之前在C#中也经常使用MVC开发模式,对其的使用有一定的了解,但是现在需要学习AngularJS,这是纯前台的JS代码,那么为什么需要学习这个呢,就是想将验证这里全部在前台执行,不需要在后台代码里面出 ...

  4. 转: IntelliJ IDEA 2016.2.2注册码

    43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiI ...

  5. Castle.ActiveRecord多数据库配置

    最近使用Castle.ActiveRecord框架,网上关于多数据支持的文章很少,因此有了这篇博文的产生. 开发工具VS2015,Sql Server2008R2 新建数据库,数据初始化脚本如下: - ...

  6. 关于异步执行(Async/await)的理解(转发)

    原文地址: http://blog.jobbole.com/85787/ 同步编程与异步编程 通常情况下,我们写的C#代码就是同步的,运行在同一个线程中,从程序的第一行代码到最后一句代码顺序执行.而异 ...

  7. Entity Framework 代码先行

    一.什么是Code First 为了支持以设计为中心的开发流程,EF还更多地支持以代码为中心 (code-centric) ,我们称为代码优先的开发,代码优先的开发支持更加优美的开发流程,它允许你在不 ...

  8. 超简单的激活Microsoft Office 2016 for Mac 方法

    1.简介: 2016年9月14日更新本博客,激活工具同样适用于Office 15.25(160817)版本.我此前在国外网站上找到一个App,下载之后运行,直接点击一个黑色开锁的标识按钮,输入系统密码 ...

  9. Linux-安装Oracle(CentOS-Oracle 12c)

    第一步:网络连接,在我的上一篇博客中有介绍,不再多说. 网络连接的目的:为了能使用yum命令,在网上直接下载文件. 第二步:前往oracle官网下载12c database服务器端的两个文件:(安装在 ...

  10. JAVA的POI操作Excel

    1.1Excel简介 一个excel文件就是一个工作簿workbook,一个工作簿中可以创建多张工作表sheet,而一个工作表中包含多个单元格Cell,这些单元格都是由列(Column)行(Row)组 ...