日期:2014-05-16  浏览次数:20326 次

JavaScript单线程还是多线程

?

自工作中有一段经历是在写JavaScript和ActionScript,遇到过前端UI与浏览器插件操作需要多线程的情况。昨天晚上又看到了这样一篇文章:《一个前端工程师眼里的NodeJs》http://www.infoq.com/cn/articles/nodejs-in-front-end-engineer-view

?

在浏览器中JavaScript与UI在同一线程中运行,实际执行中JavaScript确实为UI响应造成了一定影响,比如浏览器插件的调用后无法立即得到结果导致阻塞甚至崩溃的现象最为明显或者是用阻塞方的Ajax。当时也是抱怨JavaScript单线程的不好。

?

实际分析一下,在非同步的Ajax请求之后,直到接收到结果的这段时间里,网络并不会阻塞UI和JavaScript的执行,此时JavaScript和UI操作与网络请求的发送实际上是并行的。那么结果很明显,JavaScript确实在单线程上执行,但是浏览器却是以非单线程的方式执行。Web Worker能够直接解决JavaScript与UI占用个统一线程造成阻塞的问题,它能新开一个线程去执行JavaScript。

?

嵌套问题的解决

JavaScript对单个异步时间的处理十分容易,但是多个异步时间之间协作就很容易出现问题。例如需要需要分别请求三个参数,当三个参数全部返回后执行打印。通常这三个参数的获取都是通过异步来实现的,但是很容易会写成嵌套请求的方式。这样就导致这三个请求是串行执行,降低了性能。

下面是一个例子,start()为串行请求,执行结果是按照顺序打印出来的;paiallel()为并行请求,三个请求的结果打顺序是不确定的,效率更高,三条请求并行发出后等待结果。

?

?

?

<script>
	$(document).ready(function(){
	
		//串行获取结果,保证最后的调用
		function start( ){

			$.ajax({url:"test.xml",
					data:"text",
					error:function(){
					
						alert( "=====1=====");
						var data = 1;
						$.ajax({url:"test.xml",
								data:"text",
								error:function(){
								
									alert( "=====2=====");
									var name = 2;
									$.ajax({url:"test.xml",
											data:"text",
											error:function(){
												
												alert( "=====3=====");
												var pass = 3;
												showInfo( data, name, pass);
											}
									});
								}
						});

					}
			});
		}
		
		//并行获取数据
		function paiallel( ){

			var data = 0;
			var name = 0;
			var pass = 0;
			
			$.ajax({url:"test.xml",
					data:"text",
					error:function(){
						data = 1;
						alert( "=====FIRST=====" + data + "="+ name +"=" + pass);
						
						showInfo_2( data, name, pass);
					}
			});
			
			$.ajax({url:"test.xml",
					data:"text",
					error:function(){
						name = 2;
						alert( "=====SECOND=====" + data + "="+ name +"=" + pass);
						
						showInfo_2( data, name, pass);
					}
			});
			
			$.ajax({url:"test.xml",
					data:"text",
					error:function(){
						pass = 3;
						alert( "=====THIRD=====" + data + "="+ name +"=" + pass);
						
						showInfo_2( data, name, pass);
					}
			});
		}
		
		
		//打印数据
		function showInfo( data, name, pass){
			alert( "data=" + data + "  name=" + name + "   pass=" + pass);
		}
		
		//判断后打印结果
		function showInfo_2( data, name, pass){
			if( data != 0 && name != 0 && pass != 0){
				alert( "data=" + data + "  name=" + name + "   pass=" + pass);
			}
		}
		
		//start();
		
		paiallel();
				   
	});
</script>

?实际开发中,遇到了调用调用浏览器插件阻塞的问题。实际上并不需要插件去开启多线程去处理,保证通信不被阻塞,通过JavaScript,ActionScript都能实现线程的控制。

?