理解 Node.js 里的 process.nextTick()
来源:互联网 发布:matlab 关联矩阵 编辑:程序博客网 时间:2024/06/05 04:55
有很多人对Node.js里process.nextTick()的用法感到不理解,下面我们就来看一下process.nextTick()到底是什么,该如何使用。
Node.js是单线程的,除了系统IO之外,在它的事件轮询过程中,同一时间只会处理一个事件。你可以把事件轮询想象成一个大的队列,在每个时间点上,系统只会处理一个事件。即使你的电脑有多个CPU核心,你也无法同时并行的处理多个事件。但也就是这种特性使得node.js适合处理I/O型的应用,不适合那种CPU运算型的应用。在每个I/O型的应用中,你只需要给每一个输入输出定义一个回调函数即可,他们会自动加入到事件轮询的处理队列里。当I/O操作完成后,这个回调函数会被触发。然后系统会继续处理其他的请求。
Andy
翻译于 9个月前
2人顶
顶 翻译的不错哦!
在这种处理模式下,process.nextTick()的意思就是定义出一个动作,并且让这个动作在下一个事件轮询的时间点上执行。我们来看一个例子。例子中有一个foo(),你想在下一个时间点上调用他,可以这么做:
1
function
foo() {
2
console.error(
'foo'
);
3
}
4
5
process.nextTick(foo);
6
console.error(
'bar'
);
1
bar
2
foo
1
setTimeout(foo, 0);
2
console.log(
'bar'
);
更精确的说,process.nextTick()定义的调用会创建一个新的子堆栈。在当前的栈里,你可以执行任意多的操作。但一旦调用netxTick,函数就必须返回到父堆栈。然后事件轮询机制又重新等待处理新的事件,如果发现nextTick的调用,就会创建一个新的栈。
下面我们来看看,什么情况下使用process.nextTick():
Andy
翻译于 9个月前
2人顶
顶 翻译的不错哦!
在多个事件里交叉执行CPU运算密集型的任务:
在下面的例子里有一个compute(),我们希望这个函数尽可能持续的执行,来进行一些运算密集的任务。
但与此同时,我们还希望系统不要被这个函数堵塞住,还需要能响应处理别的事件。这个应用模式就像一个单线程的web服务server。在这里我们就可以使用process.nextTick()来交叉执行compute()和正常的事件响应。
01
var
http = require(
'http'
);
02
03
function
compute() {
04
// performs complicated calculations continuously
05
// ...
06
process.nextTick(compute);
07
}
08
09
http.createServer(
function
(req, res) {
10
res.writeHead(200, {
'Content-Type'
:
'text/plain'
});
11
res.end(
'Hello World'
);
12
}).listen(5000,
'127.0.0.1'
);
13
14
compute();
在这种模式下,我们不需要递归的调用compute(),我们只需要在事件循环中使用process.nextTick()定义compute()在下一个时间点执行即可。在这个过程中,如果有新的http请求进来,事件循环机制会先处理新的请求,然后再调用compute()。反之,如果你把compute()放在一个递归调用里,那系统就会一直阻塞在compute()里,无法处理新的http请求了。你可以自己试试。
当然,我们无法通过process.nextTick()来获得多CPU下并行执行的真正好处,这只是模拟同一个应用在CPU上分段执行而已。
Andy
翻译于 9个月前
1人顶
顶 翻译的不错哦!
保持回调函数异步执行的原则
当你给一个函数定义一个回调函数时,你要确保这个回调是被异步执行的。下面我们看一个例子,例子中的回调违反了这一原则:
1
function
asyncFake(data, callback) {
2
if
(data ===
'foo'
) callback(
true
);
3
else
callback(
false
);
4
}
5
6
asyncFake(
'bar'
,
function
(result) {
7
// this callback is actually called synchronously!
8
});
1
var
client = net.connect(8124,
function
() {
2
console.log(
'client connected'
);
3
client.write(
'world!\r\n'
);
4
});
在上面的代码里,如果因为某种原因,net.connect()变成同步执行的了,回调函数就会被立刻执行,因此回调函数写到客户端的变量就永远不会被初始化了。
这种情况下我们就可以使用process.nextTick()把上面asyncFake()改成异步执行的:
1
function
asyncReal(data, callback) {
2
process.nextTick(
function
() {
3
callback(data ===
'foo'
);
4
});
5
}
Andy
翻译于 9个月前
2人顶
顶 翻译的不错哦!
用在事件触发过程中
来看一个例子,你想写一个库实现这样的功能:从源文件里读取数据,当读取完毕后,触发一个事件同时传递读取的数据。可能你会这样写:
1
var
EventEmitter = require(
'events'
).EventEmitter;
2
3
function
StreamLibrary(resourceName) {
4
this
.emit(
'start'
);
5
6
// read from the file, and for every chunk read, do:
7
this
.emit(
'data'
, chunkRead);
8
}
9
StreamLibrary.prototype.__proto__ = EventEmitter.prototype;
// inherit from EventEmitter
1
var
stream =
new
StreamLibrary(
'fooResource'
);
2
3
stream.on(
'start'
,
function
() {
4
console.log(
'Reading has started'
);
5
});
6
7
stream.on(
'data'
,
function
(chunk) {
8
console.log(
'Received: '
+ chunk);
9
});
但是上面的代码中,将永远接收不到“start”事件,因为在这个库实例化的时候,“start”事件会被立刻触发执行,但此时事件的回调函数还没有准备好,所以在客户端根本无法接收到这个事件。同样,我们可以用process.nextTick()来改写事件触发的过程,下面是一个正确的版本:
01
function
StreamLibrary(resourceName) {
02
var
self =
this
;
03
04
process.nextTick(
function
() {
05
self.emit(
'start'
);
06
});
07
08
// read from the file, and for every chunk read, do:
09
this
.emit(
'data'
, chunkRead);
10
}
- 理解 Node.js 里的 process.nextTick()
- 理解 Node.js 里的 process.nextTick()
- 理解 Node.js 里的 process.nextTick()
- Node.js 里的 process.nextTick()
- 理解 Node.js process.nextTick() {Understanding process.nextTick()}
- node.js process nextTick作用
- process.nextTick()的理解
- node.js中的process.nextTick()和setImmediate()
- Node.js中的setImmediate()与process.nextTick
- node.js中的setImmediate()与process.nextTick()
- node中process.nextTick的理解(这个文章需要多读几遍。。)
- 《深入浅出node.js》——setImmediate()与process.nextTick()
- Node.js中对process的理解
- Node.js中nextTick、setTimeout、setImmediate的区别
- 理解 $nextTick 的作用
- Node.js的process模块
- Node.js的process模块
- Node.js的process模块
- Introduction to Oracle VM server for SPARC
- 各大公司笔试面试题之数据结构与算法
- CRON表达式详解与案例
- KanKan甄选,BaseAdapter我要对你说,ViewHolder你懂得,性能优化必读
- Unity手稿
- 理解 Node.js 里的 process.nextTick()
- 杭州武林广场塔吊倒塌 致一人死亡
- 设计模式六大原则(4):接口隔离原则
- 排序中的哨兵
- 【LeetCode】Maximum Subarray
- OpenTSDB监控系统的研究和介绍
- 单例设计模式(面试重点)
- Java爬虫,信息抓取的实现
- 宝石典故之“凤凰血染红的鸡血石”