setTimeout,异步,原理

来源:互联网 发布:中昌数据什么时候开盘 编辑:程序博客网 时间:2024/06/05 18:19

总的来说:
1. 先解释一个误区:setTimeout或者setInterval是间隔某个时间立即执行,真是这样的么?错!实际上时间参数的具体意思是:在参数指定的时间后将待执行方法放到javascript引擎的执行队列中, 如果队列中没有其他方法等待,才会立即执行setTimeout指定的方法,此时才会有立即执行的假象。

2. setTimeout(function(){XXXX},0),为什么就异步了?
这要就要说到javascript引擎到底是多线程还是单线程?从javascript引擎运行机制是怎么样的。
结合下图:
这里写图片描述

参考下面两篇文章来解释,就会基本明了。a.http://blog.csdn.net/binzai325/article/details/11773481
b.http://www.cnblogs.com/youxin/p/3354924.html

3. 定时器的延时是没有保证的。由于所有在游览器执行的js都是单线程异步事件(比如鼠标单击和定时器),执行过程中只有在有空闲的时候才会被执行。

4. 如 果你在一个大的JavaScript代码块正在执行的时候把所有的interval回调函数都囤起来的话,其结果就是在JavaScript代码块执行完 了之后会有一堆的interval事件被执行,而执行过程中不会有间隔。因此,取代的作法是浏览器情愿先等一等,以确保在一个interval进入队列的 时候队列中没有别的interval。

5. 异步事件一旦发生,就会把它的回调函数放到javascript引擎的执行队列中。

6.结论们
(1). JavaScript引擎只有一个线程,这使得异步事件必需列队等待执行。
(2). setTimeout和setInterval在如何执行代码上有着本质地区别。
(3). 如果一个timer在将要执行的时候被阻塞,它将会等待下一个时机(比预期的延时要长)。
(4). 如果interval的执行时间较长(比指定的延时长),那么它们将连续地执行而没有延时

(1). JavaScript engines only have a single thread, forcing asynchronous events to queue waiting for execution.
(2). setTimeout and setInterval are fundamentally different in how they execute asynchronous code.
(3). If a timer is blocked from immediately executing it will be delayed until the next possible point of execution (which will be longer than the desired delay).
(4). Intervals may execute back-to-back with no delay if they take long enough to execute (longer than the specified delay).

(5).对于动画来说,如果单帧的执行时间大于间隔时间,用setTimeout比用setInterval更保险。”It really depends on the situation – and how the timers are actually being used. setInterval will, most likely, get you more ‘frames’ in the animation but will certainly tax your processor more. A lot of frameworks end up using setTimeout since it degrades more gracefully on slower computers. ”
在这种情况下,采用setTimeout更保险:
setTimeout(function(){ setTimeout(arguments.callee, 10); }, 10);

主要参考:
1.http://blog.csdn.net/binzai325/article/details/11773481
2.http://www.cnblogs.com/youxin/p/3354924.html

示例代码:

setTimeout(function() {console.log("a")}, 0)for(let i=0; i<10000; i++) {}console.log("b")// 答案是:b a
var t = true;setTimeout(function(){ t = false; }, 1000);while(t){ }alert('end');//答案是:死循环……js是单线程执行的,while里面死掉的时候setTimeout里面的函数是没机会执行的。
setTimeout(function () {while(true){ }}, 1000);setTimeout(function () {alert('end 2');}, 2000);setTimeout(function () {alert('end 1');}, 100);alert('end');//答案是:end end1 然后,被while(true)阻塞,就没有下文了
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);}//答案是:死循环,回调函数被阻塞了,无法执行
原创粉丝点击