Event Loop

Event Loop是一种计算机系统的运行机制,在js这种单线程的语言中,其起着很重要的作用。

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

这个我们都很经常遇到,输出也是很容易想到是 1,3,2 ,但是究竟为什么会这样呢?之前我往往会说js有一个执行队列,setTimeout内的函数被挂起到了执行队列的最后。但是今天看了一下Event Loop,感觉自己之前对其的认知完全是错误的。
正如我们所知的,js单线程的,那么意味着,我们有多个任务时,只能排队,不像C#这种多线程语言一样,遇到多个任务时,可以在开一个线程来处理,但是有些时候(I/O操作,发起http请求)时, CPU 正在闲着,但是由于I/O操作比较慢,所以造成的就是我们的程序会一直等到I/O操作结束后再执行,于是js就引入了异步操作这一个概念,其中ajax就是一个显著的例子,我们在等待服务器响应式,我们的应用并不是卡死的,我们浏览器仍然是可以执行某些操作的。这样就引出了我们的两种任务类型,一是同步任务,而是异步任务。
同步任务在主线程上会形成一个执行栈,而我们的异步任务会被放到一个“任务队列中”,只有任务队列通知主线程该任务可以执行了,这个异步任务才会被放到执行栈中,开始执行。

具体流程如下:
1. 同步任务在主线程上形成执行栈,并开始执行;
2. 主线程之外,还存在着一个任务队列,只要异步任务运行有了结果,就会在这个任务队列中放置一个事件
3. 执行栈任务执行完毕后,系统就会读取任务队列,并且将其压入执行栈,开始执行。
4. 主线程重复着2,3

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

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

我们给定时器(setTimeout)传入的第二参数的意思是说,当主线程的执行栈为空时,在指定的毫秒数后,把我们的该函数拿到执行栈中执行。在HTML5中规定,我们的第二个参数值不得低于 4 毫秒,而之前其参数不能小于10毫秒,并且在某些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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值