精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-11-12
新开窗口的呢??
|
|
返回顶楼 | |
发表时间:2007-11-12
afcn0 写道 补充个测试
opera ie ff上面都没有显示thread2 run所以基本肯定js就是单线程的 养成写测试的习惯是很好的!事实胜于雄辩。 |
|
返回顶楼 | |
发表时间:2007-11-12
myy 写道 据我所知,IE6 (IE7标签页方式不清楚) 用 open(), _balnk, Ctrl+N 等各种方式打开的新窗口都是在独立的线程中运行的,并且同时都属于一个IE进程,"浏览器的主线程"这种说法也不确切,事实上,同一个IE进程每个IE窗口线程都是平等的,根本没有哪个是"主线程"之说。也就是说,每个IE窗口线程中都有"全套"的东西,包括 js引擎。(不过,底层的网络通讯采用了线程池,这个是共享的)。 这样,虽然"JS本身一定是单线程的",但是open()创建了两套"在不同线程中的js引擎环境",通过这样来模拟 LZ 的要求是可行的。 首先open,ctrl-n出来的窗口,与原窗口肯定同属一个进程。你用桌面图标启动的新的IE窗口就在另外一个进程里,那不在我们的讨论范围之内。其次,你说它们都在独立的窗口线程里,maybe。但我指的是主线程,就是浏览器的主控线程,其他线程都是从这个线程上分支出来的。当然,偶不清楚IE内部构造到底是如何的。但是一个IE窗口不应该有全套的东西,否则就变成一个独立的进程了。而且即使每个窗口都一个独立的js引擎,其执行也是线性化的。这很容易推理出来,因为一个窗口的脚本可以调用另一个窗口的脚本,也就是一个窗口的脚本一定可以阻塞另一个窗口的脚本。这就是我为什么说窗口对于脚本来说没有意义的原因。 测试代码: <html> <head> <title>Test JS thread</title> <script> function heavyWork(size) { info('Start a heavy work...'); size = size || 1000; var result = 0; for (var i = 0; i < size; i++) { for (var j = 0; j < size; j++) { result += Math.random(); } } info('Done.'); } function test() { window.open('test.html', '_blank', ''); heavyWork(); } function info(msg) { var now = new Date().getTime() % 100000; document.getElementById('info').innerHTML += '[' + now + '] ' + msg + '<br>'; } window.onload = function () { info('loaded.'); heavyWork(); } </script> </head> <body> <div id="info"> loading...<br> </div> <div> <button onclick="test()">Open a new window with a heavy work</button> </div> </body> </html> |
|
返回顶楼 | |
发表时间:2007-11-12
不是很理解hax写的,window.open我是这样测试的
a.htm <div id="test"> </div> <script> setTimeout(function(){ eee=window.open("b.htm"); var temp=new Date().getTime(); for (var i=0; i<100000; i++ ) { if(window.t) { document.getElementById("test").innerHTML="thread2 run"; } i=i+10000; i=i-10000; } document.getElementById("test").innerHTML+=new Date().getTime()-temp; document.documentElement.appendChild(document.createTextNode("aaaaaaaaaa")); //ie document.body.innerHTML+="aaaaaa" },0) </script> b.htm <div id="test"></div> <script> window.opener.document.documentElement.appendChild(document.createElement("hr")); //ie window.opener.document.body.innerHTML+="<hr>" </script> 经测试ff ie均表示open不用等待窗口load完毕继续执行下面代码,和XHR的异步差不多,并且open的窗口不是立即执行,而是等待主窗口js停止执行后才进行load动作,所以看到是先有aaaaa字符,后有hr的横线,open好似只是注册一个要打开的窗口,而不是立即执行,有点timeout意思 |
|
返回顶楼 | |
发表时间:2007-11-12
感谢这么多人的热烈讨论,下面的代码是我继原贴后写的测试代码,大家可以在IE、FireFox、Opera等浏览器里测试一下看看结果。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>JavaScript方法执行超时测试</title> <script> var executed = false; // 方法B是否执行的标志位 var x = 0; // 方法A中用来累加计数,使方法A执行超时 var expiredTime = 2000; function methodMain() { expiredTime = 1000 * document.counter.expiredTime.value; var t = setInterval("methodA()",0);// setInterval() //clearTimeout setInterval("methodB()",expiredTime);// setInterval() setTimeout //clearInterval } // 方法A function methodA() { // 记下methodA执行的开始时间 document.counter.aBegin.value = getNow(); var loopSize = document.counter.loopSize.value; // 方法A的耗时内容执行开始 for(i = 0;i <= loopSize;i++) { document.counter.displayBoxA.value = "i=" + i; } // 方法A的耗时内容执行结束 // 当方法A的耗时内容没有超过expiredTime的时间执行完成的话,就直接开始执行方法B methodB(); // 设置方法B执行完成的标志位 executed = true; // 记下methodA执行的结束时间 document.counter.aEnd.value = getNow() } // 方法B function methodB() { // 记下methodB执行的开始时间 document.counter.bBegin.value = getNow(); if(executed == true) { // 执行过了...... // document.counter.displayBox.value = '执行过了......'; } else { for(var i = 0;i < 100;i++) { x = x + 1; document.counter.displayBoxB.value = x; } } // 记下methodB执行的结束时间 document.counter.bEnd.value = getNow() } function getNow() { var now = new Date(); var year = now.getYear(); var month = now.getMonth(); var day = now.getDay(); var hour = now.getHours(); var minute = now.getMinutes(); var second = now.getSeconds(); // return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second; return new Date().format("yyyy-MM-dd hh:mm:ss"); } Date.prototype.format = function(format) { var o = { "M+" : this.getMonth()+1, //month "d+" : this.getDate(), //day "h+" : this.getHours(), //hour "m+" : this.getMinutes(), //minute "s+" : this.getSeconds(), //second "q+" : Math.floor((this.getMonth()+3)/3), //quarter "S" : this.getMilliseconds() //millisecond } if(/(y+)/.test(format)) format = format.replace(RegExp.$1,(this.getFullYear()+"").substr(4 - RegExp.$1.length)); for(var k in o) if(new RegExp("("+ k +")").test(format)) format = format.replace(RegExp.$1,RegExp.$1.length==1 ? o[k] : ("00"+ o[k]).substr((""+ o[k]).length)); return format; } // alert(new Date().format("yyyy-MM-dd hh:mm:ss")); </script> </head> <body> <form name="counter"> 方法A执行的开始时间:<input type="text" name="aBegin" value="" size="30"/><br/> 方法A执行的结束时间:<input type="text" name="aEnd" value="" size="30"/><br/> 方法A计数器:<input type="text" name="displayBoxA" value="0" size="20"/><br/> 方法A执行的超时限制时间:<input type="text" name="expiredTime" value="2" size="30"/>秒<br/> 方法A中用来模拟执行的死循环大小:<input type="text" name="loopSize" value="5000" size="30"/>次<br/> 方法B执行的开始时间:<input type="text" name="bBegin" value="" size="30"/><br/> 方法B执行的结束时间:<input type="text" name="bEnd" value="" size="30"/><br/> 方法B计数器:<input type="text" name="displayBoxB" value="0" size="20"/><br/> <p> </p> 执行测试:<input type="button" name="exe" value="开 始" onclick="methodMain();"/> <input type="reset" name="tReset" value="重 置"/> </form> </body> </html> |
|
返回顶楼 | |
发表时间:2007-11-13
一切都是因为Windows程序是消息驱动的,看以下Windows程序的代码:
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("HelloWin") ; HWND hwnd ; MSG msg ; WNDCLAS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuNam = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox ( NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow( szAppName, // window class name TEXT ("The Hello Program"), // window caption WS_OVERLAPPEDWINDOW, // window style CW_USEDEFAULT, // initial x position CW_USEDEFAULT, // initial y position CW_USEDEFAULT, // initial x size CW_USEDEFAULT, // initial y size NULL, // parent window handle NULL, // window menu handle hInstance, // program instance handle NULL) ; // creation parameters ShowWindow (hwnd, iCmdShow) ; // Post Message WM_SHOW UpdateWindow (hwnd) ; // Post Message WM_PAINT, 这里可能不对 while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc ; PAINTSTRUCT ps ; RECT rect ; switch (message) { case WM_CREATE: return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; GetClientRect (hwnd, &rect) ; DrawText (hdc, TEXT ("Hello, World!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, message, wParam, lParam) ; } 一个Windows程序的入口是WinMain,这里面主要部分就是一个消息循环。IE用window.open的时候没有创建新进程,所以所有的消息都是主窗口的消息处理循环在处理。IE打开一个新窗口的时候所做的事情大概就是CreateWindow、ShowWindow、UpdateWindow,这三个方法里面并不是直接显示新窗口,而时往消息队列里面放WM_SHOW、WM_PAINT等消息,要到主消息循环处理到这些消息时才显示新窗口。 另外,setTimer,setInterval也只是让系统在若干时间后放一个WM_TIMER消息到消息队列,主消息循环处理到这个消息时才会运行setTimer和setInterval时指定的回调函数。 |
|
返回顶楼 | |
发表时间:2008-06-12
貌似你执行某个方法 fun1();
估计其应该只执行30秒,如果超了。这个方法结束。执行另一个方法? 但是fun1还是在执行啊。 并且IE会挂掉的。。。 |
|
返回顶楼 | |
发表时间:2008-07-03
afcn0 写道 首先js是单线程的,lz的想法就不对,那是多线程,现在基本除了XHR的callback可以另开一个线程以外,还无法实现多线程,其次timeout是在本次js代码运行完开始计时timeout的,所以在一个耗时的函数之外timeout或者interval一个函数运行本身就是荒谬的,ie下面alert,js函数执行也会阻塞interval执行,应该其他浏览器也是这么实现,我没测试,如果interval可以实现多线程,那至少ie上面也不行
js是单线程的没错,但是setTimeout确实可以解决这个问题。因为IE识别javascript是否running过长,是对每个event触发的javascript method而言。所以,分离出独立的方法,用setTimeout触发,确实可以让IE不要跳出那个可恶的error。当然,本质上没有减少运行的总体时间。 |
|
返回顶楼 | |