今天该学习 Event Loop 啦,其实以前我写过一篇 Event Loop 的文章:javascript
浅析 JS 中的 EventLoop 事件循环(新手向)
这篇呢则是动图学 JS 系列中的,能够结合以前的文章食用~java
咱们都知道 JavaScript 是一门 单线程 的语言:同一时间只能运行一个任务。一般状况下这没什么问题,可是若是你有一个任务须要耗费 30 秒的时间,那其余任务难道都要等它 30 秒么?(因为 JS 运行在浏览器的主线程,因此这 30 秒的时间里,整个页面都会处于卡死状态)segmentfault
幸运的是,浏览器提供了一些 JS 引擎不具有的功能:Web API。它包括 DOM API
,setTimeout
,HTTP 请求
等等。这些功能均可以帮助咱们处理 异步、非阻塞 的操做。浏览器
当咱们调用一个函数时,它会被添加到一个叫作 调用栈 (call stack) 的地方,调用栈是 JS 引擎的一部分,而不是浏览器特有的。本质上它是一个栈,具备 后进先出 (Last In, First Out. 即 LIFO) 的特色。当一个函数调用完成,它就被从调用栈中弹出。异步
上图中函数 respond
返回了一个 setTimeout
函数,它也被添加到调用栈中,(setTimeout
正是 Web API 提供的功能之一:它可让咱们延迟一个任务的执行而且不阻塞主线程。)setTimeout
被调用以后,传给它的箭头函数 () => { return 'Hey' }
就被添加进了 Web API (此处简化了概念,具体能够看笔者的另外一篇文章)中。同时 setTimeout
和 respond
函数从调用栈中弹出,它们都返回了相应的值。函数
在 Web API 中,一个定时器已经建立,它将会等待 1000 ms,当时间到后,这个箭头函数并不会当即被调用栈执行,它会被添加到一个队列中,咱们暂且称之为 任务队列 (原文中叫 Callback Queue)。oop
这里可能会让人困惑:那个回调箭头函数并非在 1000ms 后被直接添加到 调用栈 的,而是被添加进了 任务队列。队列嘛,就是你们排队,先来的先服务,被谁服务?没错!就是调用栈。学习
说了这么多,终于轮到咱们的 Event Loop 登场了!若是上面的调用栈是一个银行窗口,任务队列中的回调函数是一个个排队办业务的人,那么 Event Loop 就是叫号系统!Event Loop 的惟一任务就是 链接任务队列和调用栈:spa
它不停检查 调用栈 中是否有任务须要执行,若是没有,就检查 任务队列,从中弹出一个任务,放入调用栈中,如此往复循环。
上图中终于轮到那个箭头函数接受调用了,它被调用完,也被弹出了,轻轻地它走了,只留下一个 Hey!
o(╯□╰)o线程
看图片是否是挺好理解的~ 那就来看一个例子,能够把下面的代码粘贴到浏览器的控制台亲自跑一下:
const foo = () => console.log("First"); const bar = () => setTimeout(() => console.log("Second"), 500); const baz = () => console.log("Third"); bar(); foo(); baz();
bar
。bar
返回了一个 setTimeout
函数。setTimeout
中的回调函数被添加到 Web API
,setTimeout
函数和 bar
调用完成被从调用栈弹出。foo
被调用,打印出 First
。foo
函数返回 undefined
。baz
被调用,打印出 Third
。Second
。全文就到这里啦,但愿对你理解 Event Loop 有所帮助~
本文是翻译的系列文章:
本文首发于公众号:码力全开(codingonfire)
欢迎关注获取最新内容哦~