内容简介:Node.js 中的定时器函数与web浏览器中的定时函数API 类似,增加了一个setImmediate() 函数,它们向任务队列添加定时任务setTimeout(callback, delay) delay毫秒后执行回掉函数setInterval(callback,delay) 每隔delay毫秒执行一次回掉函数
Node.js 中的定时器函数与web浏览器中的定时函数API 类似,增加了一个setImmediate() 函数,它们向任务队列添加定时任务
介绍
setTimeout(callback, delay) delay毫秒后执行回掉函数
setInterval(callback,delay) 每隔delay毫秒执行一次回掉函数
setImmediate() 将在当前事件轮询的末尾处执行。同步任务执行完后,delay不为0时首先立即执行setImmediate() 函数
console.log("1") setTimeout(func, 1000,10); function func(num) { console.log("2") } setImmediate(function(){console.log("3")}, 2000,10); console.log("4") //输出 1 4 3 2 复制代码
取消定时器,参数为每个定时器函数返回的定时器对象
clearTimeout(timeout)
clearInterval(timeout)
clearImmediate(immediate)
使用
//tcp服务端 var net = require('net') var sever = net.createServer(function (connection) { //设置服务超时时间,并返回提示消息 connection.setTimeout(1000, function () { console.log("响应超时."); connection.write('服务端响应超时了') }); setTimeout(function () { connection.on('end', function () { // console.log('客户端关闭连接') }) connection.on('data', function (data) { console.log('服务端:收到客户端发送数据为' + data.toString()) }) //给客户端响应的数据 connection.write('response hello') }, 5000) }) sever.listen(8080, function () { console.log('监听端口:8080') }) 复制代码
HTTP服务器端开始发送响应数据到HTTP客户端接收全部数据的这段时间, 如果超出设定时间,则表示响应超时,并返回超时提示
var net = require('net') var client = net.connect({ port: 8080 }) //设置请求超时时间 client.setTimeout(3000); //监听超时事件 client.on('timeout', function () { console.log("请求超时") //取消请求数据,不再发送请求 client.destroy() }) //客户端收到服务端执行的事件 client.on('data', function (data) { console.log('客户端:收到服务端响应数据为' + data.toString()) client.end() }) //给服务端传递的数据 client.write('hello') client.on('end', function () { // console.log('断开与服务器的连接') }) 复制代码
客户端设置请求超时时间,HTTP客户端发起请求到接受到HTTP服务器端返回响应头的这段时间, 如果超出设定时间,就终止请求
源码分析
lib/timers.js
setTimeout函数定义
function setTimeout(callback, after, arg1, arg2, arg3) { //第一个参数必须为函数 if (typeof callback !== 'function') { throw new ERR_INVALID_CALLBACK(callback); } //处理参数 //将第三个以后的参数包装成数组 var i, args; switch (arguments.length) { // fast cases case 1: case 2: break; case 3: args = [arg1]; break; case 4: args = [arg1, arg2]; break; default: args = [arg1, arg2, arg3]; for (i = 5; i < arguments.length; i++) { // Extend array dynamically, makes .apply run much faster in v6.0.0 args[i - 2] = arguments[i]; } break; } //生成一个Timeout 对象 const timeout = new Timeout(callback, after, args, false); active(timeout); //返回一个定时器对象 return timeout; } 复制代码
Timeout构造函数
const timeout = new Timeout(callback, after, args, false);
lib/internal/timers.js
生成的timer实例 表示Node.js层面的定时器对象,比如 setTimeout、setInterval、setImmediate返回的对象
function Timeout(callback, after, args, isRepeat) { after *= 1; // Coalesce to number or NaN if (!(after >= 1 && after <= TIMEOUT_MAX)) { if (after > TIMEOUT_MAX) { process.emitWarning(`${after} does not fit into` + ' a 32-bit signed integer.' + '\nTimeout duration was set to 1.', 'TimeoutOverflowWarning'); } after = 1; // Schedule on next tick, follows browser behavior } //延迟时间 this._idleTimeout = after; //前后指针 this._idlePrev = this; this._idleNext = this; this._idleStart = null; // This must be set to null first to avoid function tracking // on the hidden class, revisit in V8 versions after 6.2 this._onTimeout = null; //回调函数 this._onTimeout = callback; //函数参数 this._timerArgs = args; // setInterval的参数 this._repeat = isRepeat ? after : null; // 摧毁标记 this._destroyed = false; this[kRefed] = null; initAsyncResource(this, 'Timeout'); } 复制代码
Timeout.prototype.unref = function() { if (this[kRefed]) { this[kRefed] = false; decRefCount(); } return this; }; Timeout.prototype.ref = function() { if (this[kRefed] === false) { this[kRefed] = true; incRefCount(); } return this; }; 复制代码
在Timeout构造函数原型上添加unref,ref方法
unref方法取消setTimeout()、setInterval()...回掉函数的调用
ref方法恢复回掉函数的调用
active激活定时器对象
激活定时器对象,执行了 insert(item, true, getLibuvNow());
function active(item) { insert(item, true, getLibuvNow()); } 复制代码
insert
将定时器对象添加到数据结构链表内
function insert(item, refed, start) { //取出当前延迟时间 let msecs = item._idleTimeout; //判断延迟时间 if (msecs < 0 || msecs === undefined) return; // Truncate so that accuracy of sub-milisecond timers is not assumed. msecs = Math.trunc(msecs); item._idleStart = start; // Use an existing list if there is one, otherwise we need to make a new one. //根据延迟时间生成一个链表数据结构 var list = timerListMap[msecs]; if (list === undefined) { debug('no %d list was found in insert, creating a new one', msecs); const expiry = start + msecs; timerListMap[msecs] = list = new TimersList(expiry, msecs); timerListQueue.insert(list); if (nextExpiry > expiry) { scheduleTimer(msecs); nextExpiry = expiry; } } if (!item[async_id_symbol] || item._destroyed) { item._destroyed = false; initAsyncResource(item, 'Timeout'); } if (refed === !item[kRefed]) { if (refed) incRefCount(); else decRefCount(); } item[kRefed] = refed; // 把当前timeout对象添加到对应的链表上 L.append(list, item); } 复制代码
append()
node定时器是在生成对应list链表头的时候开始触发的
function append(list, item) { if (item._idleNext || item._idlePrev) { remove(item); } // 处理新节点的头尾链接. item._idleNext = list._idleNext; item._idlePrev = list; // 处理list的前后指针指向 list._idleNext._idlePrev = item; list._idleNext = item; } 复制代码
setInterval()函数的实现与setTimeout()函数类似,只有第二个参数的处理不同
const timeout = new Timeout(callback, repeat, args, true);
// setInterval的参数
this._repeat = isRepeat ? after : null;
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- cURL工具的使用技巧
- slice的一些使用技巧
- 分享一些 Broadcast 使用技巧
- AndroidStudio使用技巧-debug篇
- PyCharm/IDEA 使用技巧总结
- IDEA 超实用使用技巧分享
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Tangled Web
Michal Zalewski / No Starch Press / 2011-11-26 / USD 49.95
"Thorough and comprehensive coverage from one of the foremost experts in browser security." -Tavis Ormandy, Google Inc. Modern web applications are built on a tangle of technologies that have been de......一起来看看 《The Tangled Web》 这本书的介绍吧!
JS 压缩/解压工具
在线压缩/解压 JS 代码
HEX HSV 转换工具
HEX HSV 互换工具