作者senser (彷佛曾经一起死过)
看板Ajax
标题Re: [讨论] javascript是共时、多执行绪吗?
时间Sat Nov 5 19:29:07 2011
跟大家分享一下 我对一般常见的browser处理javascript的认知
有错误请大家不吝指教
先回答标题好了
就我所知 目前javascript在browser的implementeation中
在一个"window"下中只有一个thread 在这种情况下 你可以说javascript是单一thread
事实上大部分的时候 我们只要以这出发点来考虑问题就足够了
然而 如果你的页面中有iframe 他会有另外一个window去维护另一个thread
在同网域下 他甚至可以存取相同的global物件 造成所谓的race condition
在这种状况下 你可以说javascript 是 multi-thread 我想也是合理的
=======================
所以说 与其讨论javascript到底是不是multi-thread
其实应该讨论的问题是 browser的实作方式
首先我们开启一个页面 在这个window中会开启一个thread 处理包括
1.html的parse
2.dispatching of events
3.执行javascript
然後在parse的过程中 如果遇到某些tag像是img, embed, iframe,object 等等
他会开启另外一个thread去下载,render,或是执行iframe里面的js等等
这也是为甚麽 我们会看到在load一个网页 下载图片是分开的 每张独立下载 独立显示
同时这种作法 也大大加速了我们显示整个网页的速度
而这和我们的问题有甚麽关系呢?
在我们前端开发人员的圣经"High Performance Web Sites"中提到
我们应该尽量的把javascript放在网页的下面
为甚麽呢 因为在同一个window的single thread中 如果遇到<script>
html parsing的动作会停下来 直到
1.下载 javascript(如果是外部连结的话)
2.parse
3.执行
三个动作结束後 才会继续往下
如果这个javascript特别久 那下面网页就久久不parse,整个page loading就卡在那里
所以呢 你应该已经猜到 在你load page时 不同<script>间的javascript执行一定是分开
的
只有一段<script>跑完 才有机会继续往下parse HTML
也才有机会遇到另外一个<script> 然後执行它
而这个部分 我相信每个人都可以直观的观察到 这是single thread的感觉
那为甚麽有人会提出这类的问题
我想主要是因为javascript的一些feature如ajax,timer,alert...等等造成困惑
要理解这些困惑 我们要先理解 javascript是怎麽被执行的
以下有两种状况会执行js
1.page load时立刻执行的js
2.event handler
第一种我们已经讨论过了 很单纯的由上往下 一个一个来
第二肿 在js中我们都视为一种callback 当事件引发时 才会执行
在browser对js的处理中 它maintain一个queue叫做 "Dispatch Sequence"
当事件触发时 会立刻把handler放到里面(这动作叫作dispatch)
然後根据先来後到的顺序执行handler
而在这过程中 当前一个handler没跑完之前 下一个hander不会被执行
所以说 js依然是single thread
timeout,或是ajax callback等等 我们都要视为是一个event 一样是用这个规则在跑
所以 timeout 5秒不一定会在5秒时跑 ajax callback也不一定会在respose 抵达时马上
fire
一切都要看 前面的handler执行完了没 轮到他了没
(题外话 alert 是个special case, 每个browser不太一样 , 写js的人要尽量少用)
那最後回到我们的问题来
那个alert ABCD会不会交叉出现呢 答案是不会 (alert要少用 像是sk1765的test case就
非常好)
相信你已经知道 在timeout中的function A B都是一个event handler(callback)
在执行时 会结束才有可能去执行另一个 所以不会ABCD交叉出现
最後我想说的是 js要看成是 event-driven的东西
用thread去分析 就会陷入把他拆成一行一行看的陷阱
而event-driven 产生的timing issue 对我来说 也是js bug中最难trace的一种
文章写的有点长 但其实还有很多细节
opera这篇文章写得非常非常好 有兴趣的各位可以参考看看
http://dev.opera.com/articles/view/timing-and-synchronization-in-javascript/
※ 引述《TonyQ (自立而後立人。)》之铭言:
: ※ 引述《ec75413 (无亏/明月几时有?)》之铭言:
: : 在这里没找到类似的讨论串 网路上中文的也很少
: : 但英文还算不少
: : 所以把这个议题放上来。
: : 不知这个问题已经是老梗了 还是...?
: javascript 是同步的
: 也就是不会有两行 statement 同时执行的
: 但是他可以是多执行续。
: 也就是假设你有一个 funciont 是
: function A(){
: alert("A");
: alert("B");
: }
: function B(){
: alert("C");
: alert("D");
: }
: 透过 setTimeout / setItnerval ,
: 是有可能会发生这样的执行序
: alert("A");//from A
: alert("C");//from B
: alert("B");//from A
: alert("D");//from B
: 你把 js 底层的引擎想像成一个 queue ,
: 有要执行的指令就推进去,引擎会去跑他,
: 但同时间他只能处理一个指令。
: 一般当你真的很需要控制执行的顺序的时候,
: 我们会多加几个 flag 作为 lock ,或者自己实做queue。
: 但是基本上 javascript 要作到 java 的 synchronized keyword 做的事情,
: 是没有办法保证一定做的到的,最好尽量避免这麽严苛的状况。:P
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 71.107.60.113
1F:推 sk1765:跟我的观念差不多 不过我本来以为同一个页面放两个iframe 11/06 00:06
2F:→ sk1765:里面各自alert 会在同一时间在browser上同时出现两个dialog 11/06 00:08
3F:→ sk1765:结果也没有 所以alert这个function 他还是同一时间不会并行 11/06 00:10
4F:→ sk1765:一般的script应该就是像你说的 两个iframe个跑各的 11/06 00:13
5F:推 gs1458:感谢,对原理完全不懂,第一次就观念厘清真是再好不过了:) 11/06 03:00
7F:→ weiyucsie:不过是我的测试结果啦... 11/06 03:41
8F:→ senser:opera可以同时一堆alert吗? 这应该是multi-thread的好例子 11/06 09:55
9F:→ weiyucsie:我把alert的dialog移动一下,看见另外一个alert 11/06 16:28
10F:→ weiyucsie:所以应该是同时吧XD 11/06 16:28
11F:→ weiyucsie:咦 没注意到有另外发文XD 11/06 16:33