您的位置:首页 > 运维架构

Event Loop

2016-05-12 22:31 169 查看
Event Loop
是一种计算机系统的运行机制,在
js
这种单线程的语言中,其起着很重要的作用。

console.log(1);
setTimeout( () => console.log(2) );
console.log(3);


这个我们都很经常遇到,输出也是很容易想到是1,3,21,3,2,但是究竟为什么会这样呢?之前我往往会说
js
有一个执行队列,
setTimeout
内的函数被挂起到了执行队列的最后。但是今天看了一下
Event Loop
,感觉自己之前对其的认知完全是错误的。

正如我们所知的,
js
单线程的,那么意味着,我们有多个任务时,只能排队,不像
C#
这种多线程语言一样,遇到多个任务时,可以在开一个线程来处理,但是有些时候(I/O操作,发起http请求)时,CPUCPU正在闲着,但是由于I/O操作比较慢,所以造成的就是我们的程序会一直等到I/O操作结束后再执行,于是
js
就引入了异步操作这一个概念,其中
ajax
就是一个显著的例子,我们在等待服务器响应式,我们的应用并不是卡死的,我们浏览器仍然是可以执行某些操作的。这样就引出了我们的两种任务类型,一是同步任务,而是异步任务。

同步任务在主线程上会形成一个执行栈,而我们的异步任务会被放到一个“任务队列中”,只有任务队列通知主线程该任务可以执行了,这个异步任务才会被放到执行栈中,开始执行。

具体流程如下:

1. 同步任务在主线程上形成执行栈,并开始执行;

2. 主线程之外,还存在着一个任务队列,只要异步任务运行有了结果,就会在这个任务队列中放置一个事件

3. 执行栈任务执行完毕后,系统就会读取任务队列,并且将其压入执行栈,开始执行。

4. 主线程重复着2,3

主线程从任务队列中读取事件,并且这个过程是循环不断的,这也就是我们所说的
Event Loop


那我们的任务队列中又包含着什么呢?一是事件(浏览器交互事件,如:click,mousedown),二是被主线程挂起的函数,如我们上面例子中的那个函数。

我们给定时器(
setTimeout
)传入的第二参数的意思是说,当主线程的执行栈为空时,在指定的毫秒数后,把我们的该函数拿到执行栈中执行。在
HTML5
中规定,我们的第二个参数值不得低于44毫秒,而之前其参数不能小于1010毫秒,并且在某些dom节点操作上,其表现更为差,所以在使用动画时,我们可以借助浏览器为我们提供专门的操作动画的函数
requestAnimationFrame
,也就是请求动画帧。我们并不需要为这个函数来指定其间隔时间,因为其间隔时间就是浏览器的绘制间隔时间,这样我们当然要比自己执行间隔时间要爽的多。

下面是一个使用
requestAnimationFrame
的demo:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>请求动画帧demo</title>
<style type="text/css">
*{
margin: 0px;
padding: 0px;
}
#example{
margin: 100px 20px 0px 20px;
background: red;
height: 20px;
width: 0px;
}
#run{
margin: 5px 20px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="example">
</div>
<button id="run">run</button>
<script type="text/javascript">
var width = 0,
ele = document.getElementById("example");
function step () {
width += 1;
ele.style.width = width * 10 + "px";
ele.innerHTML = width + "%";
if (width < 100) {
requestAnimationFrame(step);
}
}
requestAnimationFrame(step);
document.getElementById("run").onclick = function () {
ele.style.width = "0px";
width = 0;
requestAnimationFrame(step);
}
</script>
</body>
</html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: