Node学习笔记(六)

        如果你习惯于浏览器javascript编程,你可能用过setTimeout和setInterval函数,这些函数允许你在给定的一段时间去执行某个任务,如下边的代码片段,一旦你加载进入这个web页面,一秒后则会向body体中追加“Hello there”字符串。
var oneSecond = 1000 * 1;
setTimeout(function() {
	document.write(‘<p>Hello there</p>’);
}, oneSecond);
setInterval通过给定一个时间间隔去重复一个函数的执行,如果你进入这个web页面,每秒将会重复调用回调函数,即每一秒会向body体中追加“Hello there”字符串。
var oneSecond = 1000 * 1;
setInterval(function() {
	document.write(‘<p>Hello there</p>’);
}, oneSecond);
对于这些函数的需求源于取代静态web页面而成为构建应用的平台,这些调度函数能帮助开发者创建周期性的表单验证,远程数据的同步,和各种需要用户界面延迟反映的交互,Node实现了这组函数,在服务器端他们能被用于协助在许多不同的任务,包括高速缓存期满时,连接池清理,会话超时,轮询和其他重复或者延迟执行的操作。

1.用setTimeout延迟执行一个函数
        在某个时候,setTimeout函数让你调度任何函数能够被执行一次,如:
var timeout_ms = 1000 * 2;    //2 seconds
var timeout = setTimeout(function() {
	console.log(“time out!”);
}, timeout_ms);
正如浏览器中javascript,setTimeout能够接受一个延迟函数作为第一个参数,并且在函数之后的参数是这个函数被执行的时间,这个参数的单位是毫秒。
调用setTimeout函数返回一个timeout执行的对象,这是一个内部对象,该对象除了使用clearTimeout取消调度的执行,不能用于任何操作。

2.用clearTimeout取消一个函数的执行
        一旦你获得了一个timeout执行者对象,你能用它通过调用clearTimeout取消调度函数的执行,如:
var timeoutTime = 1000;       // one second 
var timeout = setTimeout(function() {
	console.log("timed out!"); 
}, timeoutTime); 
clearTimeout(timeout);
在这个例子中,timeout将永远不会在控制台上打印”timed out!”,你另外能够在将来的某个时候取消调度的执行。如:
var timeout = setTimeout(function A() { 
	console.log("timed out!");
}, 2000);
setTimeout(function B() { 
	clearTimeout(timeout);
}, 1000);
3.调度和取消一个函数的重复执行
        setInterval与setTimeout类似,只是setInterval会在每个给定的时间周期连续的调度函数,你可能想用它来定期的触发执行某些类型的清理例程。收集、记录、检索,查询或其他的任何程序,你可能会发现在重复运行的基础上是有用的。
下面的代码段每秒会在控制台输出”tick”, 如:
var period = 1000;     // 1 second 
setInterval(function() {
	console.log("tick"); 
}, period);
如果你不想持续无期限的运行这个任务,或者直到它结束,你能通过调用clearInterval函数取消调度。setInterval返回一个调度执行者对象,你能提供它作为clearInterval的第一个参数去解除调度。如:
var interval = setInterval(function() { 
	console.log("tick");
}, 1000);
// ... clearInterval(interval);
4.用process.nextTick延迟一个函数的执行,直到下一个Event Loop迭代
        有时候浏览器javascript程序能用setTimeout(callback, 0)作为将来的某个时间延迟执行任务的一种方式,0值告诉javascript runtime,它应该尽可能快的在所有待处理的任务执行完后执行回调函数,这个技术有时被用于不需要立即运行的延迟操作,如,开始动画或者用户事件处理后的某些运算。
在Node中,event loop运行正如其名所示,在处理事件队列的一个循环,每次事件循环执行,被叫做tick. 你能调度一个回调函数在下一个事件循环被执行,也就是下一个tick, setTimeout如果被用在javascript runtime中,则它有自己的调度队列,process.nextTick函数被特定在Node的Event Loop. 通过使用process.nextTick(callback)替代setTimeout(callback, 0),在所有事件队列的任务被执行后,回调才会立即运行,需要注意的是,process对象是Node全局的几个对象之一。

5.阻塞事件循环
        Node和javascript runtime一般都是单线程事件循环,在每一个循环上,运行时通过调用被关联的回调函数来处理在队列的下一个事件,当该事件完成时,事件循环检索和处理下一个事件,这个模式会一直继续下去,直到队列为空,如果这些回调函数之一分配了很长的执行时间,事件循环就不能处理在此期间发生的事件,这能导致一个缓慢的应用或服务。
使用处理器密集型的功能时处理事件可能导致事件循环变得缓慢,并且事件排队越来越多,甚至可能会阻塞。这有一个阻塞实例,如:
process.nextTick(function nextTick1() {
	var a = 0;
	while(true) {
	a ++; 
	}
});
process.nextTick(function nextTick2() { 
	console.log("next tick");
});
setTimeout(function timeout() { 
	console.log("timeout");
}, 1000);
在这个例子中,nextTick2和timeout函数将永远不会有机会运行,因为在第一个nextTick函数无限的运行,事件循环被阻塞,事件调度timeout函数被期望在一秒后运行,此时,也不会运行了。当用setTimeout,回调函数会进入调度队列,在这个例子中,没有事件被派发,这是一个极限的例子,但是你能看到,运行一个CPU密集型的任务可能阻塞或者延缓你的事件循环。

5.避开事件循环阻塞
       你能够使用process.nextTick推迟非关键任务的执行到下一个事件循环,释放当前事件循环,执行其他未完成的事件。这有个例子,如果你需要移除一个已创建的临时文件,但是你在响应到客户端以前不需要移除它,你可以像这样做,如:
stream.on("data", function(data) { 
	stream.end("my response"); 
	process.nextTick(function() {
		fs.unlink("/path/to/file”);
	 });
});
6.用setTimeout代替setInterval强制序列化
        你想用一个函数做某些I/O操作,如,解析一个日志文件,将会周期性的被执行,你能够通过用setInterval,如:
var interval = 1000; 
setInterval(function() {
	my_async_function(function() { 
		console.log('my_async_function finished!’);	
	});
 },interval);
然而,你必须确保这些函数在同一时间都没执行,如果你用setInterval,你就真的不能保证,如果my_async_function需要一毫秒的时间超过了你使用的间隔时间,他们可能会在同一时间运行。
你需要强制间隔时间在my_async_function结束和下一个周期开始前之间,你能像下边这么做,如:
(function schedule() { 
	setTimeout(function do_it() {
		my_async_function(function() { 
			console.log('async is done!'); 
			schedule();
		});
	}, interval);
}());

这声明了一个函数被命名为schedule,并且在声明之后立即执行,这个shedule函数调度do_it函数在一秒后被执行,在一秒过后,这个匿名函数就会被触发,调用my_async_function函数,当这个函数完成时,匿名回调将会被执行。调用schedule函数,你将再一次调度do_it函数在以秒后被执行,重复这个周期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值