证明:JS中的setTimeout是伪多线程

有人问我在“循环ajax”那个日志后面写setTimeout是伪多线程。

那我就代码说明一下:列子3个

1、第一个

<html>
<head>
<script>
setTimeout("aa()",20);
setTimeout("dd()",20);
setTimeout("cc()",21);
function aa()
{
   document.getElementById("id1").innerHTML="执行了aa方法";
   document.getElementById("id4").innerHTML="最后执行了aa方法";
}
function dd(){
   var time1=new Date().getMilliseconds();
   for(i=0;i<1000;i++){
      j=new Date().getMilliseconds();
   }
   var time2 = new Date().getMilliseconds();
   document.getElementById("id2").innerHTML="执行dd方法 用时:"+(time2-time1)+"毫秒";
   document.getElementById("id4").innerHTML="最后执行了dd方法";
   
}
function cc(){
  document.getElementById("id3").innerHTML="执行了CC";
  document.getElementById("id4").innerHTML="最后执行了cc方法";
  
}
</script>
<head>
<body>
<div id="id1"></div>
<div id="id2"></div>
<div id="id3"></div>
<div id="id4"></div>
</body>
</html>

 

执行结果是:

执行了aa方法
执行dd方法 用时:16毫秒
执行了CC
最后执行了cc方法
 
按理说cc方法是在21毫秒的时候执行。结果应该如下:
执行了aa方法
执行了dd方法 用时:16毫秒
执行了cc
最后执行了dd
此刻可以证明:当dd方法运行的时候一直占用着线程,dd方法用时16毫秒了,cc运行时间和dd运行时间仅差1毫秒,却仍在dd执行之后才执行。
 
2、简单的settimeout
        setTimeout(function () { while (true) { } }, 1000);
        setTimeout(function () { alert('end 2'); }, 2000);
        setTimeout(function () { alert('end 1'); }, 100);
        alert('end');执行的结果是弹出‘end’‘end 1’,然后浏览器假死,就是不弹出‘end 2’。也就是说第一个settimeout里执行的时候是一个死循环,这个直接导致了理论上比它晚一秒执行的第二个settimeout里的函数被阻塞,这个和我们平时所理解的异步函数多线程互不干扰是不符的。
 
 
3、ajax请求回调
接着我们来测试一下通过xmlhttprequest实现ajax异步请求调用,主要代码如下:
        var xmlReq = createXMLHTTP();//创建一个xmlhttprequest对象
        function testAsynRequest() {
            var url = "/AsyncHandler.ashx?action=ajax";
            xmlReq.open("post", url, true);
            xmlReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xmlReq.onreadystatechange = function () {
                if (xmlReq.readyState == 4) {
                    if (xmlReq.status == 200) {
                        var jsonData = eval('(' + xmlReq.responseText + ')');
                        alert(jsonData.message);
                    }
                    else if (xmlReq.status == 404) {
                        alert("Requested URL is not found.");
                    } else if (xmlReq.status == 403) {
                        alert("Access denied.");
                    } else {
                        alert("status is " + xmlReq.status);
                    }
                }
            };
            xmlReq.send(null);
        }
        testAsynRequest();//1秒后调用回调函数
        
        while (true) {
 
        }
      在服务端实现简单的输出:
        private void ProcessAjaxRequest(HttpContext context)
        {
            string action = context.Request["ajax"];
            Thread.Sleep(1000);//等1秒
            string jsonObject = "{\"message\":\"" + action + "\"}";
            context.Response.Write(jsonObject);
        }理论上,如果ajax异步请求,它的异步回调函数是在单独一个线程中,那么回调函数必然不被其他线程”阻挠“而顺利执行,也就是1秒后,它回调执行弹出‘ajax’,可是实际情况并非如此,回调函数无法执行,因为浏览器再次因为死循环假死。
结论:根据实践结果,可以得出,javascript引擎确实是单线程处理它的任务队列的。在javascript里实现异步编程很大程度上就是一种障眼法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值