setTimeout,它就是一个定时器,用来指定某个函数在多少毫秒之后执行
# setTimeout用法
var timeoutID = setTimeout(function[, delay, arg1, arg2, ...]);
var timeoutID = setTimeout(function[, delay]);
var timeoutID = setTimeout(code[, delay]);
@前端进阶之旅: 代码已经复制到剪贴板
- 第一个参数为函数或可执行的字符串(比如
alert('test'),此法不建议使用) - 第二个参数为延迟毫秒数,可选的,默认值为
0. - 第三个及后面的参数为函数的入参。
setTimeout的返回值是一个数字,这个值为timeoutID,可以用于取消该定时器
# setTimeout在浏览器中的实现
- 浏览器渲染进程中所有运行在主线程上的任务都需要先添加到消息队列,然后事件循环系统再按照顺序执行消息队列中的任务。
- 在 Chrome 中除了正常使用的消息队列之外,还有另外一个消息队列(我们可以称为延迟队列),这个队列中维护了需要延迟执行的任务列表,包括了定时器和 Chromium 内部一些需要延迟执行的任务。所以当通过 JavaScript 创建一个定时器时,渲染进程会将该定时器的回调任务添加到延迟队列中。
比如这样的一段代码:
function foo(){
console.log("test")
}
var timeoutID = setTimeout(foo,100);
@前端进阶之旅: 代码已经复制到剪贴板
当通过 JavaScript 调用
setTimeout设置回调函数的时候,渲染进程将会创建一个回调任务,包含了回调函数foo、当前发起时间、延迟执行时间等,其模拟代码如下所示
struct DelayTask{
int64 id;
CallBackFunction cbf;
int start_time;
int delay_time;
};
DelayTask timerTask;
timerTask.cbf = foo;
timerTask.start_time = getCurrentTime(); //获取当前时间
timerTask.delay_time = 100;//设置延迟执行时间
@前端进阶之旅: 代码已经复制到剪贴板
- 创建好回调任务之后,就会将该任务添加到延迟执行队列中。那这个回调任务,什么时候会被执行呢?
- 浏览器中有个函数是专门用来处理延迟执行任务的,暂且称为ProcessDelayTask,它的主要逻辑如下:
void ProcessTimerTask(){
//从delayed_incoming_queue中取出已经到期的定时器任务
//依次执行这些任务
}
TaskQueue task_queue;
void ProcessTask();
bool keep_running = true;
void MainTherad(){
for(;;){
