高级前端js【Q220】请简述一下 event loop

请简述一下 event loop

Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 221

Author 回答者: martin-yin

image

heap(堆):对象被分配在堆中,堆是一个用来表示一大块(通常是非结构化的)内存区域的计算机术语。 stack(栈):函数调用形成了一个由若干帧组成的栈。 WebAPIS:囊括 Web 强大脚本能力的每个 API 参考资料, 包括 DOM 、所有相关的 APIs 及可以用来构建 Web 的相关接口。 队列(event queue || Callback Queue):一个 JavaScript 运行时包含了一个待处理消息的消息队列。每一个消息都关联着一个用以处理这个消息的回调函数

event loop 运行图解

setTimeout(() => {
    console.log(1)
}, 100)
console.log(2);
setTimeout(() => {
    console.log(3)
}, 0)
// 2
// 1
// 3

未标题-1

看图我们可以了解到,setTimeout(() => {console.log(1)}, 0) 会在Stack执行,在放入WebAPIs中当成一个匿名函数执行,匿名函数执行完毕之后会放入Callback Queue 中。 console.log(2) 则直接被推入Stack 中执行。

setTimeout(() => {console.log(3)}, 0) 同样的执行后放入WebAPIs中当成一个匿名函数执行,在放入Callback Queue中。当同步任务执行完之后,才会将Callback Queue 队列中的方法推入Stack中。

因为JS是单线程的,单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。为了解决排除等待问题,JS的任务分为同步任务(synchronous)和异步任务(asynchronous)。 所有同步任务都在主线程上执行,形成一个Stac)。异步任务(如果是WebAPI 则会进入WebAPI,例如ajax setTimeout)不进入主线程,而是进入另一 Callback Queue。同步任务顺序执行,只有执行栈中的同步任务执行完了,系统才回读取任务队列中可以执行的异步任务,才会把此异步任务从事件队列中放入执行栈中执行,如此循环,直至所有任务执行完毕。

这就是EventLoop

Author 回答者: shfshanyue

@martin-yin 这个网站好评啊!

Author 回答者: 18062706139fcz

image

heap(堆):对象被分配在堆中,堆是一个用来表示一大块(通常是非结构化的)内存区域的计算机术语。 stack(栈):函数调用形成了一个由若干帧组成的栈。 WebAPIS:囊括 Web 强大脚本能力的每个 API 参考资料, 包括 DOM 、所有相关的 APIs 及可以用来构建 Web 的相关接口。 队列(event queue || Callback Queue):一个 JavaScript 运行时包含了一个待处理消息的消息队列。每一个消息都关联着一个用以处理这个消息的回调函数

event loop 运行图解

setTimeout(() => {
    console.log(1)
}, 100)
console.log(2);
setTimeout(() => {
    console.log(3)
}, 0)
// 2
// 1
// 3

未标题-1 未标题-1

看图我们可以了解到,setTimeout(() => {console.log(1)}, 0) 会在Stack执行,在放入WebAPIs中当成一个匿名函数执行,匿名函数执行完毕之后会放入Callback Queue 中。 console.log(2) 则直接被推入Stack 中执行。

setTimeout(() => {console.log(3)}, 0) 同样的执行后放入WebAPIs中当成一个匿名函数执行,在放入Callback Queue中。当同步任务执行完之后,才会将Callback Queue 队列中的方法推入Stack中。

因为JS是单线程的,单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。为了解决排除等待问题,JS的任务分为同步任务(synchronous)和异步任务(asynchronous)。 所有同步任务都在主线程上执行,形成一个Stack)。异步任务(如果是WebAPI 则会进入WebAPI,例如ajax setTimeout)不进入主线程,而是进入另一 Callback Queue。同步任务顺序执行,只有执行栈中的同步任务执行完了,系统才会读取任务队列中可以执行的异步任务,才会把此异步任务从事件队列中放入执行栈中执行,如此循环,直至所有任务执行完毕。

这就是EventLoop

Author 回答者: Ghaining

setTimeout(() => {
    console.log(1)
}, 100)
console.log(2);
setTimeout(() => {
    console.log(3)
}, 0)

// 2 // 3 // 1

Author 回答者: 601odd

答案是不是错了啊 放在浏览器是2 3 1 现在这个网站放上去也是2 3 1 image

Author 回答者: Patrickill

答案错了吧应该是 2 3 1 应该是先是console.log(3)直接放入宏任务队列,在1之前放入的