也许是以前搞桌面程序开发的缘故,我一直以为IE弹出的alert是模式对话框,觉得它会阻断线程。但其它浏览器的alert并不使用IE样式的对话框,所以alert到底是不是阻断了线程就需要重新考虑了。事实上alert不会阻断线程,而且在实现上还存在浏览器差异。
这货是不是看起来很眼熟?它是IE的alert吗?不是!这货是我刚用C++写的小程序
#pragma comment(lib,"User32.lib")
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"main\"")
#include <Windows.h>
int main(){
MessageBox(0,"我是alert吗?","来自网页的消息",MB_ICONWARNING);
return 0;
};
它是线程阻断的,要不然程序就立即结束了。但是IE中的alert虽然和这货长的一样,却不是线程阻断的。虽然最终用的也是这货,但在调用过程中有其它封装。比如把它放入子线程调用什么的,无论它是怎么实现的,总之它不会阻断页面的线程!
我为什么这么说?众所周知,网页是单线程的,如果把仅有的线程都给阻断了,谁还能负责处理这个alert对话框之外的东西呢?在IE中alert完全是模式对话框风格,它弹出后锁定了主窗体,所以我们很难测试。但是其它浏览器呢?最典型的就是Firefox,它的alert甚至看起来像页面级的。Chrome在alert时也依然可以操作导航栏和上面的按钮。这些按钮的功能同样是页面线程负责的,如果不信可以运行个死循环的代码后再点击刷新按钮试试。在死循环的状态下,页面是无法刷新和跳转的,因为线程死了。
除了死循环外,同步请求也会挂起线程,试试下面这个程序吧 with(new XMLHttpRequest())
open("GET","/test.php",false),send();//test.php
sleep(5);
同步请求时导航栏也是死的,和死循环一样的状态,只是它不占用太多系统资源。
alert的对话框和这些东西比起你来就温柔多了,所以说alert并没有阻断线程,只是模拟了模式对话框弹出,并阻断了JavaScript相关的消息,对于一些系统消息仍然会处理。
这篇文章貌似有点缺乏论证的感觉,因为这个论证会涉及很多东西,之后的文章将会给出更有力的证据。