内容简介: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;
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Analytics 2.0
Avinash Kaushik / Sybex / 2009-10-26 / USD 39.99
The bestselling book Web Analytics: An Hour A Day was the first book in the analytics space to move beyond clickstream analysis. Web Analytics 2.0 will significantly evolve the approaches from the fir......一起来看看 《Web Analytics 2.0》 这本书的介绍吧!
JSON 在线解析
在线 JSON 格式化工具
RGB转16进制工具
RGB HEX 互转工具