源文档地址javascript
如何你跟我同样的话,那么你必定会爱上javascript!虽然它不是一种比较完美的编程语言,可是严格地说,还有其它比javascript更完美的语言来设计web吗?因此请忽视javascript的缺陷吧。我喜欢web工做,而javascript使得我能够用其来创建applications,从而跟web上的用户联系起来!java
可是若是你深究javascript——你会发现,它的一些内部概念你须要花费许多时间才能真正理解!其中一个概念就是Event Loop,可能一个在web开发中工做了几年的开发人员也没有真正理解其含义和工做原理,无论怎样,我但愿经过这篇文章,能带给你一些启发:什么是event loop?其实它并非那么难以理解的!node
咱们一般所说的javascript,都是指浏览器端使用的javascript——由于咱们写的javascript代码大多数是用在客户端的!无论怎样,理解这些概念和技术是很是重要的:一、Javascript Engine(好比 Chrome's V8),二、Web API(如 DOM),三、Event Loop 和 Event Quene。git
你可能看过上面列举的这些概念以后,你可能会这样想:“好复杂呀!”,确实是这样的!可是经过这篇文章待会儿你会发现,其实它们并无那么复杂!github
在介绍event loop以前,咱们须要对javascript engine作一个简单的理解来明白它是作什么的!web
有几种不一样的js引擎,可是最流行的一个当属谷歌的V8了(它并不只仅在浏览器环境中使用,经过nodejs,它也在服务器端使用)。可是js引擎的工做究竟是什么呢?其实,引擎的工做很是简单——它会遍历咱们写的全部js代码,而后一个一个的执行它们。也就是说咱们的js是单线程的,单线程很差的地方就是,若是你同步执行了一段很长时间的代码的话,那么这段代码后面的逻辑会被阻塞从而等待好久才能执行。同门一般都不想写阻塞的代码——特别是在浏览器中,设想若是你点击了一个按钮以后去执行了一个很长时间的阻塞代码,这会致使你的页面的其它交互效果会暂停,严重影响用户体验!编程
那么js引擎是怎么知道一个一个的处理代码呢?其实它使用了call stack(调用栈)。你能够把调用栈看做一个电梯——第一个进电梯的人最后一个出来,最后一个进电梯的人第一个出来!浏览器
咱们来看一个例子:服务器
/*Within main.js*/
var firstFunction = function(){
console.log("I'm first!");
};
var secondFunction = function(){
firstFunction();
console.log("I'm second!");
};
secondFunction();
/*Results: *=> I'm first! *=> I'm second! */复制代码
首先,js引擎会维护一个调用栈序列的:app
到如今,咱们已经知道js引擎的调用栈的原理了,那么咱们回到刚才所讨论的阻塞代码的问题上,咱们都知道应该避免写阻塞代码!庆幸的是,js提供了一种机制来实现非阻塞:异步回调函数!咱们又接触了一个概念,是否是觉得这个概念很牛逼呢?其实并非,异步回调函数跟你写过的其它的普通的函数同样的!只不过它不是同步执行的,若是你熟悉的setTimeout函数的话,它就是异步的,咱们来看一个例子:
/* Within main.js */
var firstFunction = function () {
console.log("I'm first!");
};
var secondFunction = function () {
setTimeout(firstFunction, 5000);
console.log("I'm second!");
};
secondFunction();
/* Results: * => I'm second! * (And 5 seconds later) * => I'm first! */复制代码
咱们看一下调用栈序列是怎么样的!(为了尽快说明问题,咱们快进了)
当调用栈在调用setTimeout的时候,发生了一块儿特别的事情——浏览器会把setTimeout的回调函数放到(在这个例子中就是firstFunction)Event Table中。你能够把Event Table理解成为一个注册机构,调用栈会告诉Event Table去注册一个特别的函数,当特定的事件发生的时候去执行它,当特定的事件发生时,Event Table只是简单的把这个函数移动到Event Quene里面,Event Quene只是一个放置函数即将执行的暂存区,最后由Event Quene把函数移动到调用栈中。
你可能会问,Event Quene何时知道把回调函数放回到调用栈中呢?好,js引擎听从一个简单的规则:浏览器中存在一个进程会不断地去检查调用栈是否为空,同时,不管任什么时候候只要调用栈为空,它会检查Event Quene是否有待执行的函数队列!若是调用栈为空,那么它会把Event Quene队列里面的第一个函数放到调用栈中,若是Event Quene为空的话,那么这个进程将会无限期地来回地进行检查,好吧——咱们描述的这个就是所谓的Event Loop!