- 浏览: 1920538 次
- 性别:
- 来自: 福建莆田@广州
文章分类
最新评论
-
YuLimin:
关于开发者版本费用等问题请见:Have questions? ...
IBM于2009.06.19推出开发者免费版WebSphere Application Server -
YuLimin:
1、传统WAS : WebSphere Application ...
IBM于2009.06.19推出开发者免费版WebSphere Application Server -
chenlei65368:
咋加啊,总司令
微信JavaEye老炮群的入群标准-2009年之前注册JavaEye的技术人员 -
kkllmey:
怎么进呢。留个群号吧。
微信JavaEye老炮群的入群标准-2009年之前注册JavaEye的技术人员 -
Mr.TianShu:
3792274
微信JavaEye老炮群的入群标准-2009年之前注册JavaEye的技术人员
我的一个想法是这样的,如下代码:
异想天开,想用 setTimeout 来做个 workaround ,但是 setTimeout / setInterval 方法是在它所在的方法执行完之后才开始计时的,于是,光当一声,这个 workaround 不成立。
各位有没有做过类似的需求,如何解决的呢?
js是单线程的没错,但是setTimeout确实可以解决这个问题。因为IE识别javascript是否running过长,是对每个event触发的javascript method而言。所以,分离出独立的方法,用setTimeout触发,确实可以让IE不要跳出那个可恶的error。当然,本质上没有减少运行的总体时间。
据我所知,IE6 (IE7标签页方式不清楚) 用 open(), _balnk, Ctrl+N 等各种方式打开的新窗口都是在独立的线程中运行的,并且同时都属于一个IE进程,"浏览器的主线程"这种说法也不确切,事实上,同一个IE进程每个IE窗口线程都是平等的,根本没有哪个是"主线程"之说。也就是说,每个IE窗口线程中都有"全套"的东西,包括 js引擎。(不过,底层的网络通讯采用了线程池,这个是共享的)。
这样,虽然"JS本身一定是单线程的",但是open()创建了两套"在不同线程中的js引擎环境",通过这样来模拟 LZ 的要求是可行的。
首先open,ctrl-n出来的窗口,与原窗口肯定同属一个进程。你用桌面图标启动的新的IE窗口就在另外一个进程里,那不在我们的讨论范围之内。其次,你说它们都在独立的窗口线程里,maybe。但我指的是主线程,就是浏览器的主控线程,其他线程都是从这个线程上分支出来的。当然,偶不清楚IE内部构造到底是如何的。但是一个IE窗口不应该有全套的东西,否则就变成一个独立的进程了。而且即使每个窗口都一个独立的js引擎,其执行也是线性化的。这很容易推理出来,因为一个窗口的脚本可以调用另一个窗口的脚本,也就是一个窗口的脚本一定可以阻塞另一个窗口的脚本。这就是我为什么说窗口对于脚本来说没有意义的原因。
测试代码:
养成写测试的习惯是很好的!事实胜于雄辩。
是否是新开窗口,对于JS来说没有意义。
除非是两个完全没有任何关联的浏览器会话,理论上是可以在两个独立线程中的。
顺带说一下,JS本身一定是单线程的(除了特定的引擎扩展之外),这并不妨碍浏览器的其它部分是多线程的(问题是现有的浏览器实现,往往把脚本执行放在浏览器的主线程中)。但是其它任何一种异步机制或者外部多线程,如果牵涉到脚本,最终都会归并到JS的这一个线程中。所以XHR是异步的,CSS渲染是异步的,打开一个新窗口是异步的……都不能改变JS脚本的执行顺序。
据我所知,IE6 (IE7标签页方式不清楚) 用 open(), _balnk, Ctrl+N 等各种方式打开的新窗口都是在独立的线程中运行的,并且同时都属于一个IE进程,“浏览器的主线程”这种说法也不确切,事实上,同一个IE进程每个IE窗口线程都是平等的,根本没有哪个是“主线程”之说。也就是说,每个IE窗口线程中都有“全套”的东西,包括 js引擎。(不过,底层的网络通讯采用了线程池,这个是共享的)。
这样,虽然“JS本身一定是单线程的”,但是open()创建了两套“在不同线程中的js引擎环境”,通过这样来模拟 LZ 的要求是可行的。
是否是新开窗口,对于JS来说没有意义。
除非是两个完全没有任何关联的浏览器会话,理论上是可以在两个独立线程中的。
顺带说一下,JS本身一定是单线程的(除了特定的引擎扩展之外),这并不妨碍浏览器的其它部分是多线程的(问题是现有的浏览器实现,往往把脚本执行放在浏览器的主线程中)。但是其它任何一种异步机制或者外部多线程,如果牵涉到脚本,最终都会归并到JS的这一个线程中。所以XHR是异步的,CSS渲染是异步的,打开一个新窗口是异步的……都不能改变JS脚本的执行顺序。
我的意思是,由于JS是单线程执行的(除了某些带有扩展特性的引擎,如rhino),所以脚本其实没有可能进行真正意义上的多线程。
注意setTimeout/setInterval并非JS规范的一部分,而是浏览器提供的特性。而且它们本质上只是一个排程器,不可能中断尚未执行完成的脚本或者重入任何一个方法。否则必然会出现语义上的问题。真正多线程,必定要带有其它的原语,如锁定、同步、信号量——JS本身一样都没有。
我们可以用setTimeout来实现Executor和Queue,但是进入一个queue的任何一个任务一旦执行,就不可能被中断,只有它执行完成了,其他task才有机会执行。所以你必须手动把heavy的task分解成一系列小的task,才能模拟多线程。
未来的JS 2.0,我们仍然不会有多线程(除了引擎自己的扩展),但是我们有了yield,能以协程方式进行并行编程!
当然是先B后A,因为根据timer的设定,B在A前。
我说的意思恰恰是,B总在A前,即使B是一个heavytask超过了A的timer所设定的时间,但是由于script引擎是单线程的,A总是要等到B执行完毕后才有机会执行。
You r wrong. They always in one script thread.
这个我没明白
为什么新开个窗口后, 新窗口内执行的 js 和 原窗口是一个线程????
比如 原窗口内循环执行一个函数.
中途开了一个新窗口 新窗口内也是调用一个函数
难道那个窗口的函数要执行完了
原窗口的才会继续执行下去????
如果open的窗口 和原窗口是一个 script thread
那么 通过 <a href=... target='_blank' >....
打开的呢?? 也是???
你可以尝试一下你所构思的测试例子,看看结果如何。
<!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 = 3000; // 方法A function methodA( ) { // 第一句就执行定时器 setTimeout("methodB()",expiredTime);// setInterval() // 方法A的耗时内容执行开始 x = x + 1; document.counter.displayBox.value = x; for(i = 0;i < 80000;i++) { window.status = "i=" + i; } // 方法A的耗时内容执行结束 // 当方法A的耗时内容没有超过expiredTime的时间执行完成的话,就直接开始执行方法B methodB(); // 设置方法B执行完成的标志位 executed = true; } // 方法B function methodB() { if(executed == true) { // 执行过了...... } else { // 执行...... } } </script> </head> <body> <form name="counter"> <input type="text" name="displayBox" value="0" size="10"/> </form> <script> methodA(); </script> </body> </html>
异想天开,想用 setTimeout 来做个 workaround ,但是 setTimeout / setInterval 方法是在它所在的方法执行完之后才开始计时的,于是,光当一声,这个 workaround 不成立。
各位有没有做过类似的需求,如何解决的呢?
评论
37 楼
andyhu1007
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。当然,本质上没有减少运行的总体时间。
36 楼
xqstation
2008-06-12
貌似你执行某个方法 fun1();
估计其应该只执行30秒,如果超了。这个方法结束。执行另一个方法?
但是fun1还是在执行啊。
并且IE会挂掉的。。。
估计其应该只执行30秒,如果超了。这个方法结束。执行另一个方法?
但是fun1还是在执行啊。
并且IE会挂掉的。。。
35 楼
cbhyk
2007-11-13
一切都是因为Windows程序是消息驱动的,看以下Windows程序的代码:
一个Windows程序的入口是WinMain,这里面主要部分就是一个消息循环。IE用window.open的时候没有创建新进程,所以所有的消息都是主窗口的消息处理循环在处理。IE打开一个新窗口的时候所做的事情大概就是CreateWindow、ShowWindow、UpdateWindow,这三个方法里面并不是直接显示新窗口,而时往消息队列里面放WM_SHOW、WM_PAINT等消息,要到主消息循环处理到这些消息时才显示新窗口。
另外,setTimer,setInterval也只是让系统在若干时间后放一个WM_TIMER消息到消息队列,主消息循环处理到这个消息时才会运行setTimer和setInterval时指定的回调函数。
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时指定的回调函数。
34 楼
YuLimin
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>
33 楼
afcn0
2007-11-12
不是很理解hax写的,window.open我是这样测试的
a.htm
b.htm
经测试ff ie均表示open不用等待窗口load完毕继续执行下面代码,和XHR的异步差不多,并且open的窗口不是立即执行,而是等待主窗口js停止执行后才进行load动作,所以看到是先有aaaaa字符,后有hr的横线,open好似只是注册一个要打开的窗口,而不是立即执行,有点timeout意思
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意思
32 楼
hax
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>
31 楼
hax
2007-11-12
afcn0 写道
补充个测试
opera ie ff上面都没有显示thread2 run所以基本肯定js就是单线程的
opera ie ff上面都没有显示thread2 run所以基本肯定js就是单线程的
养成写测试的习惯是很好的!事实胜于雄辩。
30 楼
fins
2007-11-12
新开窗口的呢??
29 楼
afcn0
2007-11-12
补充个测试
opera ie ff上面都没有显示thread2 run所以基本肯定js就是单线程的
<div id="test"> </div> <script> function aaa(){ var temp=new Date().getTime(); for (var i=0;i<10000 ;i++ ) { if(window.t) { document.getElementById("test").innerHTML="thread2 run"; } i=i+10000; i=i-10000; } document.getElementById("test").innerHTML+=new Date().getTime()-temp; return i; } function bbb(){ t=1234; } setTimeout(aaa,5); setTimeout(bbb,10); </script>
opera ie ff上面都没有显示thread2 run所以基本肯定js就是单线程的
28 楼
afcn0
2007-11-12
没有过多分析,只是思维上的猜测,window.open必须等待打开页面onload彻底执行完才返回,所以和原页面是单线程(此点有待实验证实),但是即便如此setTimeout可以注册在load事件后执行,所以应该可以实现多窗口多js并行
timeout interval应该看js解释器是如何实现的,比如ie就永远是单线程,alert都会终止timer的计时,但是其他解释器则不然,所以至少ie上面是没有多线程一说的,也许ff或其他确实可以实现多timer并行执行(没测试),但是还是那句话,ie不支持也是有其道理的,不要把web弄的太复杂了
...我一个菜鸟被楼上大哥称为大牛,烧的难受
timeout interval应该看js解释器是如何实现的,比如ie就永远是单线程,alert都会终止timer的计时,但是其他解释器则不然,所以至少ie上面是没有多线程一说的,也许ff或其他确实可以实现多timer并行执行(没测试),但是还是那句话,ie不支持也是有其道理的,不要把web弄的太复杂了
...我一个菜鸟被楼上大哥称为大牛,烧的难受
27 楼
fins
2007-11-12
晕 本来以为 hax把我教明白了 这一下又糊涂了
有没有官方的说法啊????
afcn0 hax jindw .... 等等各位js研究的大牛们
快出来给个正确答案啊
有没有官方的说法啊????
afcn0 hax jindw .... 等等各位js研究的大牛们
快出来给个正确答案啊
26 楼
myy
2007-11-12
hax 写道
fins 写道
这些我理解了
但是 这个还是没明白
但是 这个还是没明白
是否是新开窗口,对于JS来说没有意义。
除非是两个完全没有任何关联的浏览器会话,理论上是可以在两个独立线程中的。
顺带说一下,JS本身一定是单线程的(除了特定的引擎扩展之外),这并不妨碍浏览器的其它部分是多线程的(问题是现有的浏览器实现,往往把脚本执行放在浏览器的主线程中)。但是其它任何一种异步机制或者外部多线程,如果牵涉到脚本,最终都会归并到JS的这一个线程中。所以XHR是异步的,CSS渲染是异步的,打开一个新窗口是异步的……都不能改变JS脚本的执行顺序。
据我所知,IE6 (IE7标签页方式不清楚) 用 open(), _balnk, Ctrl+N 等各种方式打开的新窗口都是在独立的线程中运行的,并且同时都属于一个IE进程,“浏览器的主线程”这种说法也不确切,事实上,同一个IE进程每个IE窗口线程都是平等的,根本没有哪个是“主线程”之说。也就是说,每个IE窗口线程中都有“全套”的东西,包括 js引擎。(不过,底层的网络通讯采用了线程池,这个是共享的)。
这样,虽然“JS本身一定是单线程的”,但是open()创建了两套“在不同线程中的js引擎环境”,通过这样来模拟 LZ 的要求是可行的。
25 楼
fins
2007-11-12
非常感谢
以前对这方面的了解确实太少了 现在知道了
谢谢
以前对这方面的了解确实太少了 现在知道了
谢谢
24 楼
hax
2007-11-12
fins 写道
这些我理解了
但是 这个还是没明白
但是 这个还是没明白
是否是新开窗口,对于JS来说没有意义。
除非是两个完全没有任何关联的浏览器会话,理论上是可以在两个独立线程中的。
顺带说一下,JS本身一定是单线程的(除了特定的引擎扩展之外),这并不妨碍浏览器的其它部分是多线程的(问题是现有的浏览器实现,往往把脚本执行放在浏览器的主线程中)。但是其它任何一种异步机制或者外部多线程,如果牵涉到脚本,最终都会归并到JS的这一个线程中。所以XHR是异步的,CSS渲染是异步的,打开一个新窗口是异步的……都不能改变JS脚本的执行顺序。
23 楼
hax
2007-11-12
fins 写道
to hax
我明白你的意思了
其实你是指, 理论上我说的对
但是实际情况中 我例子中的A方法会一直占有CPU ,使得方法B根本得不到运行的机会,对吧?
我明白你的意思了
其实你是指, 理论上我说的对
但是实际情况中 我例子中的A方法会一直占有CPU ,使得方法B根本得不到运行的机会,对吧?
我的意思是,由于JS是单线程执行的(除了某些带有扩展特性的引擎,如rhino),所以脚本其实没有可能进行真正意义上的多线程。
注意setTimeout/setInterval并非JS规范的一部分,而是浏览器提供的特性。而且它们本质上只是一个排程器,不可能中断尚未执行完成的脚本或者重入任何一个方法。否则必然会出现语义上的问题。真正多线程,必定要带有其它的原语,如锁定、同步、信号量——JS本身一样都没有。
我们可以用setTimeout来实现Executor和Queue,但是进入一个queue的任何一个任务一旦执行,就不可能被中断,只有它执行完成了,其他task才有机会执行。所以你必须手动把heavy的task分解成一系列小的task,才能模拟多线程。
未来的JS 2.0,我们仍然不会有多线程(除了引擎自己的扩展),但是我们有了yield,能以协程方式进行并行编程!
22 楼
fins
2007-11-12
这些我理解了
但是 这个还是没明白
这个我没明白
为什么新开个窗口后, 新窗口内执行的 js 和 原窗口是一个线程????
比如 原窗口内循环执行一个函数.
中途开了一个新窗口 新窗口内也是调用一个函数
难道那个窗口的函数要执行完了
原窗口的才会继续执行下去????
如果open的窗口 和原窗口是一个 script thread
那么 通过 <a href=... target='_blank' >....
打开的呢?? 也是???
但是 这个还是没明白
引用
这个我没明白
为什么新开个窗口后, 新窗口内执行的 js 和 原窗口是一个线程????
比如 原窗口内循环执行一个函数.
中途开了一个新窗口 新窗口内也是调用一个函数
难道那个窗口的函数要执行完了
原窗口的才会继续执行下去????
如果open的窗口 和原窗口是一个 script thread
那么 通过 <a href=... target='_blank' >....
打开的呢?? 也是???
21 楼
hax
2007-11-12
fins 写道
to Hax
下面一段代码,确实是先执行的B, 而不是A执行完之后再执行的B啊
下面一段代码,确实是先执行的B, 而不是A执行完之后再执行的B啊
当然是先B后A,因为根据timer的设定,B在A前。
我说的意思恰恰是,B总在A前,即使B是一个heavytask超过了A的timer所设定的时间,但是由于script引擎是单线程的,A总是要等到B执行完毕后才有机会执行。
20 楼
hax
2007-11-12
fins 写道
hax 写道
myy 写道
可以考虑用 window.open() 开新窗口实现,这个在IE下肯定是多线程的
You r wrong. They always in one script thread.
这个我没明白
为什么新开个窗口后, 新窗口内执行的 js 和 原窗口是一个线程????
比如 原窗口内循环执行一个函数.
中途开了一个新窗口 新窗口内也是调用一个函数
难道那个窗口的函数要执行完了
原窗口的才会继续执行下去????
如果open的窗口 和原窗口是一个 script thread
那么 通过 <a href=... target='_blank' >....
打开的呢?? 也是???
你可以尝试一下你所构思的测试例子,看看结果如何。
19 楼
halfmile
2007-11-10
JavaScript 虚拟机在一个浏览器中有多个实例吗?如果没有就无法实现多进程了。何况即便可以多进程,JavaScript也没有提供权限来取消进程,如果简单的抛弃进程,那么是否会造成内存泄漏呢?
一般耗时的function,大多是罗列或者递归操作。如果是两种操作的话,可以用一些技巧模拟可取消的进程。一个方法是把function里面的状态取出来放在外面,然后套一个很短的(1ms)interval来反复执行。当一定条件满足的时候,比如完成或者超时,那clearInterval就可以了。
一般耗时的function,大多是罗列或者递归操作。如果是两种操作的话,可以用一些技巧模拟可取消的进程。一个方法是把function里面的状态取出来放在外面,然后套一个很短的(1ms)interval来反复执行。当一定条件满足的时候,比如完成或者超时,那clearInterval就可以了。
18 楼
fins
2007-11-10
to hax
我明白你的意思了
其实你是指, 理论上我说的对
但是实际情况中 我例子中的A方法会一直占有CPU ,使得方法B根本得不到运行的机会,对吧?
我明白你的意思了
其实你是指, 理论上我说的对
但是实际情况中 我例子中的A方法会一直占有CPU ,使得方法B根本得不到运行的机会,对吧?
发表评论
-
第一本Flash SEO书?Search Engine Optimization for Flash
2008-11-09 10:55 1746原来我们在做Flex或Flash应用的时候,都会谈及搜索方面的 ... -
Adobe OpenSource Flex 4每晚构建(Nightly Builds)版本可以下载了
2008-10-05 12:04 2413Adobe OpenSource Flex 4(Gumbo)可 ... -
《CSS实战手册》(CSS: The Missing Manual)中文勘误列表
2007-10-05 18:35 7203错误难免,有则改之,无则加勉! 此文专门用于译文勘误,我会及 ... -
秋风秋雨正是读书时《CSS实战手册》(CSS: The Missing Manual)中秋佳节登场亮相了
2007-09-25 08:29 628810年前,当我在记 ... -
JavaScript 解析 XML 时如何通过名称直接取到值?
2007-01-26 18:56 7267JavaScript 解析 XML 时如何通过名称直接取到值 ... -
JS-UIX - Terminal一个以浏览器操作的Unix Shell的demo
2006-12-30 01:38 5469JS-UIX - Terminal(http://www.ma ... -
Flex开发中使用Ant编译.mxml成.swf后,在.swf里使用Session的解决方法
2006-04-30 20:30 4817Flex开发中使用Ant编译.mx ...
相关推荐
在上述代码中,complete回调函数会在Ajax请求完成时执行,无论成功、失败还是超时。通过检查status参数的值,我们可以判断请求是否因为超时而结束,并执行相应的处理操作。 总结以上所述,为jQuery的Ajax请求添加...
JavaScript中的`setTimeout()`函数是一个非常重要的工具,它允许开发者安排代码在特定的延迟后执行,这对于创建动态效果、异步处理、以及定时任务等场景非常有用。下面将详细讲解`setTimeout()`函数的使用方法和相关...
在JavaScript中,窗口对象(Window)是全局对象,提供了对浏览器窗口的各种控制,包括控制窗口的状态栏、访问窗口的历史记录以及设置超时等功能。 1. **控制窗口状态栏** 窗口状态栏通常位于浏览器窗口的底部,...
而在异步编程中,即使某个任务需要时间(如网络请求),程序也不会阻塞,而是继续执行其他任务,当异步任务完成时再通知程序处理结果。这使得用户体验更加流畅,尤其是在需要网络交互的场景下。 在网页中,我们通常...
超时调用的使用场景包括但不限于:动画和定时任务的实现,以及在一些复杂的事件处理中等待一段时间后再执行操作。例如,在一个表单验证的场景中,可以在用户停止输入一段时间后才开始验证,这可以通过setTimeout来...
在计算机编程中,计时器是一种非常重要的工具,它用于执行特定操作或在特定时间间隔后触发事件。计时器的实现方式多种多样,适用于不同的编程语言和应用场景。本篇文章将深入探讨计时器的基本原理、常见实现方法以及...
同步请求会在请求完成之前阻塞浏览器的主线程,而异步请求则允许浏览器在等待响应时继续执行其他任务。 同步请求造成浏览器假死的问题通常发生在执行耗时的网络请求时。在这个请求完成之前,浏览器不会渲染任何内容...
4. **轮询循环**:doTimeout支持在满足特定条件前持续执行某个函数,这在实现条件检测或者等待某个状态改变的场景下非常实用。 5. **去块优化**:与原生的setTimeout相比,doTimeout在执行延迟任务时考虑到了事件...
要实现自动消失的功能,我们可以使用 setTimeout 函数,该函数可以在指定的时间后执行某个函数。在本例中,我们可以使用 setTimeout 函数来关闭消息提示框。例如,我们可以在显示消息提示框时使用 setTimeout 函数,...
在实际应用中,可能还需要结合其他技巧,如设置User-Agent、处理验证码、模拟登录等,以适应各种复杂的网页抓取需求。记住,始终尊重网站的robots.txt文件,遵循抓取规则,以免引起不必要的麻烦。
这个过程通常包括设置URL、请求方法、超时时间等参数,然后发送请求并接收服务器返回的响应。 在获取到HTML源代码后,接着是解析和抽取目标内容。这通常涉及对HTML的解析,易语言可能没有内置的HTML解析库,但可以...
例如,在处理异步请求时,可以根据返回的数据类型进行不同的处理,比如获取JSON数据后在前端进行动态显示,或者更新页面的某个部分等。$.ajax()方法的灵活使用,大大简化了AJAX技术的应用,使得开发者能够更加专注于...
在Web应用中,我们经常遇到需要等待某个操作完成,但又不能无限期等待的情况,这时就需要设定一个超时时间来确保程序的正常运行。jeefo_timeout作为jeefo框架的一个组成部分,为开发者提供了优雅地处理这种问题的...
使用 `delay` 函数可以实现延迟执行,而 `timeout` 则可以为异步操作设置超时,防止程序因为某个操作卡住。 6. **错误处理**: 在异步编程中,错误处理是关键。Async.js 提供了一个 `tryCatch` 高阶函数,可以...
下面我们将详细介绍如何在Vue.js环境中实现刷新当前页面的方法。 **一、刷新原理** 刷新页面的基本思路是利用Vue Router的导航机制。首先创建一个空页面(例如:/user/back),当用户完成某个操作后,页面会跳转到...
为了提高测试的灵活性,某些动作命令可以附加“并等待”后缀,如“点击并等待”,表示在执行动作之后,Selenium会等待浏览器加载新的页面,直至某个条件满足或者超时。 辅助命令主要用于检查应用程序的状态,并将...
2. 异步请求:文档强调了AJAX请求的异步特性,意味着当Web浏览器发送AJAX请求到服务器时,它不需要等待服务器响应,而可以继续执行其他代码。这使得用户体验更加流畅,因为页面不需要重新加载即可与服务器进行交互。...
除了简单的监听事件,我们还可以利用Promise链来实现更复杂的逻辑,比如在某个特定的加载状态之后执行特定的操作,或者在加载过程中添加超时机制。 6. **async/await** ES7引入的async/await语法可以让Promise的...
DWR (Direct Web Remoting) 是一个开源的Java库,它允许JavaScript在浏览器端与服务器端的Java对象进行直接交互,实现AJAX功能。在DWR3中,"精确推送"(也称为反向推送或服务器推送)是一种技术,允许服务器主动地将...
这个库特别适用于那些需要在特定事件触发后才能继续执行的场景,例如异步操作、动画完成或者用户确认等。 `wait-for-event` 库的核心功能在于它允许开发者注册一个回调函数,该函数会在指定的事件被触发时得到执行...