原文链接:dev.to/lydiahallie…

概览
setTimeout(() => console.log("Second"), 500) 调用 500ms 后,并不会立即被添加到调用栈(call back)执行,而是被放入队列中(queue)中,待当前调用栈为空时,被事件循环推入调用栈执行。
正文
JavaScript 是 单线程(single-threaded) 的,即同一时刻,只能执行一个任务。对于普通低开销任务,我们可能发现不了这个特性的缺点。现在假设有一个将要耗费 30s 才能完成的任务需要处理,问题就来了——我们必须要等待这个 30s 任务结束后,才能继续执行后续代码,在此期间,我们什么都做不了(JavaScript 默认运行在浏览器的主线程上,导致整个界面都无法响应,卡成狗)😬。套一句流行的话:都2020年了,我们拒绝这样低效🙅♂️。
幸运的是,浏览器给我们提供了 JavaScript 引擎本身没有提供的接口:Web API。Web API 是指包括 DOM API、setTimeout、HTTP 请求在内的等一系列 API 的集合。Web API 的出现,帮助了我们实现异步的、非阻塞的程序🚀
当我们调用一个函数的时候,它会被添加到一个被称为“调用栈(call stack)”的结构里。调用栈是 JS 引擎的一部分,而不是由浏览器特别提供的。栈结构的特点是后入先出(LIFO),可以想象叠在一起的书本。当函数调用完毕返回一个值时,此时函数从栈中弹出(pop)👋

1 || 函数调用时被推入栈,待函数执行完成返回一个值后,从栈中弹出。
根据上面的图解,分析一下执行过程:
- 调用函数
greet,greet()入栈,执行函数体,返回字符串"Hello"。函数调用完毕,从栈中弹出。 - 调用函数
respond,respond()入栈,执行函数体。 - 调用
setTimeout(),得到一个定时器id,执行完毕(同时回调函数() => { return "Hey!" }被添加到 Web API),从栈中弹出, respond()返回一个值(定时器id),执行完毕,从栈中弹出。
接着往下看

2 || SetTimeout 由浏览器提供,由 Web API 负责它的回调。
计时器会在 Web API 中运行 100ms(即前面 SetTimeout(() => {...}, 1000) 函数中第二个参数值)后,不会被立即添加到调用栈中,而是会被放进一个称为队列(queue)的结构里。

3 || 当定时器完成(即此例中的 1000ms),回调会被放进回调队列中。
这部分需要着重说一下:SetTimeout(() => {...}, 1000) 的意思并非说,SetTimeout 的回调函数会在 1000ms 后被添加到调用栈!它的意思是 1000ms 后背添加到_队列_。顾名思义,在队列中,回调函数要等到轮到它时。
现在我们等待了一段时间……事件循环是时间登场了——它是连接队列和调用栈的桥梁。如果当前调用栈是空的(即之前的调用的函数顺利执行,返回了值,从栈中弹出了),此时,队列中的_第一项_会被添加到调用栈中。

4 || 事件循环查看回调队列和调用栈。如果调用栈当前是空的,那么事件循环会将队列里的第一项推入到调用栈中。
回调被添加到调用栈中,调用执行,返回一个值,然后从栈中弹出。

5 || 回调被添加到调用栈执行,返回一个值后,即从栈中弹出。
当然,以图解的方式讲述事件循环,看起来还是很悦目的。不过我们还是要不断不断练习,才能真正掌握。看下下面的代码,你能推导出执行过程和打印结果吗?
const bar = () => setTimeout(() => console.log("Second"), 500);
const foo = () => console.log("First");
const baz = () => console.log("Third");
bar();
foo();
baz();
我们下面来分析一下,这段代码在浏览器中的执行过程。

- 调用
bar。bar返回了一个setTimeout函数的执行结果。 setTimeout的回调被添加到了 Web API 中,setTimeout和bar从调用栈中弹出。- 定时器开始运行。同时,
foo被调用,打印"First"。foo返回undefined,baz被调用,setTimeout回调被添加到队列。 baz打印"Third"。事件循环在baz返回后,查看调用栈是空的,然后将队列中的回调添加到调用栈中。setTimeout回调函数打印"Second"。
这就是全部执行过程了,理解了吗?
(正文完)
广告时间(长期有效)
我有一位好朋友开了一间猫舍,在此帮她宣传一下。现在猫舍里养的都是布偶猫。如果你也是个爱猫人士的话,欢迎扫一扫她的【闲鱼】二维码。不买也不要紧,看看也行。
(完)