JavaScript定时机制、以及浏览器渲染机制 浅谈
昨晚,朋友拿了一道题问我:
a.onclick = function(){
setTimeout(function() {
//do something ...
},0);
};
JavaScript API 文档明确定义:setTimeout的第二个参数意义为隔多少毫秒后,回调方法就会被执行。那么可以推断出:这里设成0毫秒,就立即被执行了。
—————— 既然立即执行,为什么这段代码的作者为什么要 舍近求远?难道作者写代码的时候喝醉了?
显然不是!
这个问题 David Flanagan 在《Javascript 权威指南》中有阐述:当 setTimeout 的延迟时间设置为 0 的时候,回调函数不会马上执行,而是进入队列。
David Flanagan 在《Javascript权威指南》里并没有详细描述Javascript队列的具体运作方式,现在我来大致说一下这个问题。
JavaScript 引擎是单线程模式运行的,浏览器无论在什么时候都只且只有一个JavaScript线程在运行程序。
要说清楚这些问题,还得从浏览器内核处理定时器(setTimeout、setInterval)和响应浏览器事件说起。
浏览器内核实现允许多个线程异步执行,这些线程在内核制控下相互配合以保持同步。假设某一浏览器内核的实现至少有三个常驻线程:javascript引擎线程、界面渲染线程、浏览器事件触发线程。除些以外,也有一些执行完就终止的线程:如Http请求线程等,这些异步线程都会产生不同的异步事件。
下面通过一个图来阐明单线程的JavaScript引擎与另外那些线程是怎样互动通信的。虽然每个浏览器内核 (流行浏览器内核有:Trident[IE内核]、Gecko[Firefox内核]、Presto[Opera内核]、Webkit[Chrome、Safari] 等) 实现细节不同,但这其中的调用原理都是大同小异。

浏览器中的JavaScript引擎是基于事件驱动的。这里的事件可看作是浏览器派给它的各种任务,如调用setTimeout 添加一个任务,也可来自浏览器内核的其它线程,如界面元素鼠标点击事件、定时触发器时间到达通知、异步请求状态变更通知等。
从代码角度看来任务实体就是各种回调函数,JavaScript引擎一直等待着任务队列中任务的到来。由于单线程关系,这些任务得进行排队,一个接着一个被引擎处理。
图形界面渲染线程:
该线程负责渲染浏览器界面HTML元素,当界面需要重绘或由于某种操作引发回流时,该线程就会执行。
我今天想重点解释JavaScript定时机制,但这时有必要说说渲染线程,因为该线程与JavaScript引擎线程是互斥的!这一点Yahoo 前端攻城师在博客上有一篇详细文章描述这个问题。这也容易理解:因为JavaScript脚本是可操纵DOM元素,在修改这些元素属性同时渲染界面,那么渲染线程前后获得的元素数据就可能不一致了。
在JavaScript引擎运行脚本期间,浏览器渲染线程都是处于挂起状态的,也就是说被”冻结”了(题外话:YSlow优化网页建议指南指出:js文件要放在html内容的下面,就是因为加载 js 的时候,会阻塞 DOM树的构建。这一点可以再Yahoo工程师的前端优化方案里面看到)。
GUI事件触发线程:
JavaScript脚本的执行不影响html元素事件的触发,在Time1时间段内,用户点击鼠标键,点击事件被浏览器事件触发线程捕捉后,形成一个鼠标点击事件,对于JavaScript引擎线程来说,这事件是由其它线程异步传到任务队列尾的,由于引擎正在处理 Time1 时的任务,这个鼠标点击事件就会排队。
定时触发线程:
注意这里的浏览器模型定时计数器并不是由JavaScript引擎计数的,因为JavaScript引擎是单线程的,如果处于阻塞线程状态就不能计时,它必须依赖外部来计时并触发定时,所以队列中的定时事件也是异步事件。
后来朋友说道:既然JavaScript是单线程运行,那XMLHttpRequest 的异步链接是怎么回事?
其实异步请求是由浏览器新开一个线程请求!当请求的状态变更时,如果先前已设置回调,这异步线程就产生状态变更事件放到JavaScript引擎的处理队列中等待处理!
所以当任务被处理时,JavaScript引擎始终是单线程运行回调函数!
JavaScript定时机制、以及浏览器渲染机制 浅谈的更多相关文章
- [转]浏览器渲染机制——一定要放在body底部的js引用
转自:http://blog.csdn.net/u012251421/article/details/50536265 说明: 本文提到的浏览器均是指Chrome. “script标签“指的都是普通的 ...
- 转:JavaScript定时机制、以及浏览器渲染机制 浅谈
昨晚,朋友拿了一道题问我: a.onclick = function(){ setTimeout(function() { //do something ... },0); }; //~~~ 我只知道 ...
- 理解WebKit和Chromium: Chromium WebView和Chrome浏览器渲染机制
转载请注明原文地址:http://blog.csdn.net/milado_nju ## 数据对比 前面介绍过Chromium WebView的时候,说过有关ChromiumWebView同Chrom ...
- 网页性能优化:防止JavaScript、CSS阻塞浏览器渲染页面
网页中引用的外部文件: JavaScritp.CSS 等常常会阻塞浏览器渲染页面.假设在 <head> 中引用的某个 JavaScript 文件由于各种不给力需要2秒来加载,那么浏览器渲染 ...
- 转---JS 一定要放在 Body 的最底部么?聊聊浏览器的渲染机制
作者:德来 segmentfault.com/a/1190000004292479 如有好文章投稿,请点击 → 这里了解详情 一.从一个面试题说起 面试前端的时候我喜欢问一些看上去是常识的问题.比如: ...
- 关于JavaScript定时机制的总结
要理解JavaScript的定时机制,就要知道JavaScript的运行机制. 首先声明,JavaScript是单线程运行(JavaScript引擎线程)事件驱动. 一.浏览器中有多个线程 一款浏览器 ...
- JavaScript可否多线程? 深入理解JavaScript定时机制
JavaScript的setTimeout与setInterval是两个很容易欺骗别人感情的方法,因为我们开始常常以为调用了就会按既定的方式执行, 我想不少人都深有同感, 例如 setTimeout( ...
- 深入理解JavaScript定时机制和定时器注意问题
容易欺骗别人感情的JavaScript定时器 JavaScript的setTimeout与setInterval是两个很容易欺骗别人感情的方法,因为我们开始常常以为调用了就会按既定的方式执行, 我想不 ...
- JavaScript可否多线程? 深入理解JavaScript定时机制(转载)
说明:最近写 js 时需要用setinterval函数做定时操作,谁知道,刚开始后运行完好,但一段时间后他就抽风了,定时任务运行的时间间隔越来越短,频率加快,这是一个完全不能容忍的问题,带着一个可以出 ...
随机推荐
- 5V与3.3V器件电平转换
源:5V与3.3V器件电平转换 当你使用3.3V的单片机的时候,电平转换就在所难免了,经常会遇到3.3转5V或者5V转3.3V的情况,这里介绍一个简单的电路,他可以实现两个电平的相互转换(注意是相互哦 ...
- 【floyd】 poj 2240
#include <iostream> #include <map> #include <string> #include <memory.h> usi ...
- 将自己apk打包进其他apk安装思路
把Apk 作为asset 资源编译进去,运行的时候释放出来再安装. dexclassloader加载. 动态加载. 把一个apk写成安装器,默认安装的话,需要root或者需要漏洞利用.
- IE6 7 父级元素的overflow:hidden 是包不住子级的relative
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Android复习--广播
广播有两种方式,一种静态广播,一种动态广播. 静态广播-->静态广播接收器在配置文件里面注册. 动态广播-->而动态广播接收器在代码里面注册. 广播的发送: Context.sendBro ...
- SpringMvc MultipartFile 图片文件上传
spring-servlet.xml <!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 --> <bean id="multipar ...
- python第一天(文件流以及控制流)简单总结
第一天的python学习主要是: (1)对python的一个大致了解 值得注意的是在window下开发要注意path的问题. (2)对python控制流的一个了解 常用的if ,while ,for ...
- 说说Core Animation
前言 本次分享将从以下方面进行展开: 曾被面试官问倒过的问题:层与视图的关系 CALayer类介绍及层与视图的关系 CAShapeLayer类介绍 UIBezierPath贝塞尔曲线讲解 CoreAn ...
- Bootstrap学习指南
一.Bootstrap简介 二.Bootstrap安装 三.Bootstrap CSS 四.Bootstrap 布局组件 五.Bootstrap 插件 六.Bootstrap定制
- js 日期控件laydate使用
官网 http://sentsin.com/layui/laydate/ 1. 下载官网上的压缩包,解压后只需要复制laydate 文件夹到你的项目中; 2. 在页面引入 <script t ...