Js引擎
来源:互联网 发布:c语言黑色编程界面 编辑:程序博客网 时间:2024/06/05 16:10
js引擎是单线程执行的
var isStop = true; setTimeout(function () { isStop= false; }, 500); while (isStop); alert('END');isStop默认是true的,在while中是死循环的.最后的alert是不会执行的. 我添加了一个定时器,1秒后将isStop改为false. 如果说js引擎是多线程的,那么在1秒后,alert就会被执行.然而实际情况是,页面会永远死循环下去.alert并没有执行.这很好的证明了,settimeout并不能作为多线程使用.js引擎执行是单线程的.
alert("start"); setTimeout(() => {
alert("done");
}, 0); alert("end");这是一个很简单的实验,如果settimeout(0)会立即执行,那么这里的执行结果就应该是start、done、end . 然而实际的结果却是start、end、done
对于这个结果我们的解释是:
js引擎与GUI引擎是互斥的
谈到这里,就不得不说浏览器的另外一个引擎---GUI渲染引擎. 在js中渲染操作也是异步的.比如dom操作的代码会在事件队列中生成一个任务,js执行到这个任务时就会去调用GUI引擎渲染.
js语言设定js引擎与GUI引擎是互斥的,也就是说GUI引擎在渲染时会阻塞js引擎计算.原因很简单,如果在GUI渲染的时候,js改变了dom,那么就会造成渲染不同步. 我们需要深刻理解js引擎与GUI引擎的关系,因为这与我们平时开发息息相关,我们时长会遇到一些很奇葩的渲染问题.看这个例子
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title></title></head><body> <table border=1> <tr><td><button id='do'>Do long calc - bad status!</button></td> <td><div id='status'>Not Calculating yet.</div></td> </tr> <tr><td><button id='do_ok'>Do long calc - good status!</button></td> <td><div id='status_ok'>Not Calculating yet.</div></td> </tr> </table> <script>function long_running(status_div) { var result = 0; for (var i = 0; i < 1000; i++) { for (var j = 0; j < 700; j++) { for (var k = 0; k < 300; k++) { result = result + i + j + k; } } } document.querySelector(status_div).innerHTML = 'calclation done' ;}document.querySelector('#do').onclick = function () { document.querySelector('#status').innerHTML = 'calculating....'; long_running('#status');};document.querySelector('#do_ok').onclick = function () { document.querySelector('#status_ok').innerHTML = 'calculating....'; window.setTimeout(function (){ long_running('#status_ok') }, 0);};</script></body></html>
我们希望能看到计算的每一个过程,我们在程序开始,计算,结束时,都执行了一个dom操作,插入了代表当前状态的字符串,Not Calculating yet.和calculating....和calclation done.计算中是一个耗时的3重for循环. 在没有使用settimeout的时候,执行结果是由Not Calculating yet 直接跳到了calclation done.这显然不是我们希望的.而造成这样结果的原因正是js的事件循环单线程机制.dom操作是异步的,for循环计算是同步的.异步操作都会被延迟到同步计算之后执行.也就是代码的执行顺序变了.calculating....和calclation done的dom操作都被放到事件队列后面而且紧跟在一起,造成了丢帧.无法实时的反应.这个例子也告诉了我们,在需要实时反馈的操作,如渲染等,和其他相关同步的代码,要么一起同步,要么一起异步才能保证代码的执行顺序.在js中,就只能让同步代码也异步.即给for计算加上settimeout.
settimeout(0)的作用
不同浏览器的实现情况不同,HTML5定义的最小时间间隔是4毫秒. 使用settimeout(0)会使用浏览器支持的最小时间间隔.所以当我们需要把一些操作放到下一帧处理的时候,我们通常使用settimeout(0)来hack.
requestAnimationFrame
这个函数与settimeout很相似,但它是专门为动画而生的.settimeout经常被用来做动画.我们知道动画达到60帧,用户就无法感知画面间隔.每一帧大约16毫秒.而requestAnimationFrame的帧率刚好是这个频率.除此之外相比于settimeout,还有以下的一些优点:
- requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧,每帧大约16毫秒.
- 在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
- 但它优于setTimeout/setInterval的地方在于它是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销。
总结:
- 浏览器的内核是多线程的,它们在内核制控下相互配合以保持同步,一个浏览器至少实现三个常驻线程:javascript引擎线程,GUI渲染线程,浏览器事件触发线程。
- javascript引擎是基于事件驱动单线程执行的.JS引擎一直等待着任务队列中任务的到来,然后加以处理,浏览器无论什么时候都只有一个JS线程在运行JS程序。
- 当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。但需要注意 GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。
- 当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。
- js引擎
- js引擎
- JS引擎
- Js引擎
- JS引擎
- 排版引擎与js引擎
- “EasyTemplate” JS模板引擎
- js 引擎 JavaScriptCore
- js时间计数引擎
- JS游戏引擎大全
- 浅析js模板引擎
- jdk6 中的js引擎
- verlet-js物理引擎
- js 引擎 JavaScriptCore
- QT 的JS引擎
- TrimPath - Js模板引擎
- js模版引擎。
- js模板引擎介绍
- C# 正则表达式 使用介绍(备查阅)
- 两道有趣的算法题(只有思路)
- 用nvm管理不同版本的node和npm
- 每天一个Linux命令(57):ss命令
- 3.工作流学习——Activiti流程定义管理三步曲
- Js引擎
- 对input的值实时监听
- sessionStorage、localStorage和cookie之间的区别
- Test
- selenium2-测试用例(2)
- js清除浏览器缓存的几种方法
- tensorflow代码自动升级
- 每天一个Linux命令(58):telnet命令
- Coderforces Taxi