理解 Node.js 里的 process.nextTick()

有很多人对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

时间: 2024-11-10 19:43:38

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

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  nodjsapi  node.jsapi   |举报 |字号 订阅 下载LOFTER 我的照片书  | nodejs的process是一个全局对象,他提供了一些方法和属性,node.js官方的API说的很简单,并没有把一些详细的应用方法和作用写出来,下面结合我自己的学习,做一下小结吧.1.Even

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

理解Node.js 为了理解Node.js是如何工作的,首先你需要理解一些使得Javascript适用于服务器端开发的关键特性.Javascript是一门简单而又灵活的语言,这种灵活性让它能够经受住时间的考验.函数.闭包等特性使Javascript成为一门适合Web开发的理想语言. 有一种偏见认为Javascript是不可靠的,然而事实并非如此.人们对Javascript的偏见来源于DOM,DOM是浏览器厂商提供的用于Javascript与浏览器交互的API,不同浏览器厂商实现的DOM存在差异.

理解Node.js的事件轮询

前言 总括 : 原文地址:理解Node.js的事件轮询 Node小应用:Node-sample 智者阅读群书.亦阅历人生 正文 Node.js的两个基本概念 Node.js的第一个基本概念就是I/O操作开销是巨大的: 所以,当前变成技术中最大的浪费来自于等待I/O操作的完毕.有几种方法能够解决性能的影响: 同步方式:按次序一个一个的处理请求.利:简单.弊:不论什么一个请求都能够堵塞其它全部请求. 开启新进程:每一个请求都开启一个新进程.利:简单:弊:大量的链接意味着大量的进程. 开启新线程:每一

浅理解node.js

最近开始了解node.js,在这里把最近看的(七天学会nodejs)大概串一下,加深一下理解. node.js是一个解析器——一种运行环境,允许JS使用运行环境提供的内置对象和方法做一些事情.例如fs/http内置对象. ——运行在服务端的JavaScript 1 先来个实际点的小例子,感受一下nodejs var http = require('http'); http.createServer(function (request, response) { response.writeHead

理解Node.js(译文)

正文 当我向别人介绍Node.js 的时候一般会有两种反应,要么是立马就弄明白它是个什么玩意儿,要么是被它搞的很糊涂. 如果你现在还处于后者,下面就是我对于node的解释: 它是一个命令行工具,你可以下载一个tarball文件,编译然后安装源文件: 它可以让你在你的终端输入node my_app.js来运行Javascript程序: Node的JS代码是由 V8 javascript 引擎(就是那个使得Chrome如此之快的东西)所执行的: Node提供了诸如访问网络或是操作文件系统的Javas

深入理解Node.js基于事件驱动的回调

回调和异步调用的关系 首先明确一点,回调并非是异步调用,回调是一种解决异步函数执行结果的处理方法.在异步调用,如果我们希望将执行的结果返回并且处理时,可以通过回调的方法解决.为了能够更好的区分回调和异步回调的区别,我们来看一个简单的例子,代码如下: function waitFive(name, function_name){ var pus = 0; var currentDate = new Date(); while(pus < 5000){ var now = new Date(); p

理解 Node.js 的 Event loop

问题 考察如下代码,脑回路中运行并输出结果: console.log("1"); setTimeout(function setTimeout1() { console.log("2"); process.nextTick(function nextTick1() { console.log("3"); }); new Promise(function promise1(resolve) { console.log("4");

【译】理解node.js事件轮询

Node.js的第一个基本论点是I/O开销很大. 当前编程技术中等待I/O完成会浪费大量的时间.有几种方法可以处理这种性能上的影响: 同步:每次处理一个请求,依次处理.优点:简单:缺点:任何一个请求都可以阻塞所有其他的请求. Fork一个新进程:开一个新进程来处理每个请求.优点:容易:缺点:不能很好的扩展,成百上千个连接意味着成百上千个进程.fork()函数相当于Unix程序员的锤子,因为它很有用,每个问题看起来就像一个钉子,通常会被过度使用.(译者注:直译比较拗口,我理解的意思是,Unix程序

理解Node.js安装及模块化

1.安装Node Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效. Node.js 的包管理器 npm(Node Package Manage),是全球最大的开源库生态系统. 中文网:http://nodejs.cn/英文网:https://nodejs.org 2.REPL(交互式解释器) REPL(Read Eval Print Loop:交互式解释器),表示一个电脑的环境