写在前面:
文章脉路:
- 案例
- 初步猜测结果
- 测试验证,发现和预想不一致,为什么?
- 引出原理讲解
- 把原理套在案例里
- 更多案例印证原理
关键词:
单线程single-threaded
异步 async (asynchronous)
回调 callback
执行栈/调用栈 a call stack
任务队列 callback; queue
事件循环 event loop
不完全译文:
原文地址:If Javascript Is Single Threaded, How Is It Asynchronous?
原文作者: @Brian Barbour
Javascript是一门单线程的编程语言。这意味着它将使用一个执行栈以及一个内存堆。正如单线程给我们的印象那样,它按顺序执行代码,并且必须先完成执行片段代码(a piece code),然后才能继续执行下一个代码。它是同步的,但有时可能是有害的。例如,如果某个函数需要一段时间才能执行或必须等待某件事,那么它会同时冻结所有内容。
窗口警报功能就是一个很好的例子。 alert("Hello World")
直到您单击确定并关闭警报,您才能与该网页进行交互。you are stuck。
So how do we get asynchronous code with Javascript then?
Well, 我们要为此感谢Javascript引擎(V8,Spidermonkey,JavaScriptCore等),这些引擎具有可在background处理这些任务的Web API。执行栈认得出Web API的(functions),并且交给浏览器去处理。浏览器完成这些任务后,它们将返回并作为callback被压入stack。
The call stack recognizes functions of the Web API and hands them off to be handled by the browser. Once those tasks are finished by the browser, they return and are pushed onto the stack as a callback.
打开控制台并键入window然后按Enter。您将看到Web API必须提供的大多数内容。其中包括ajax调用,事件监听器,提取API和setTimeout之类的内容。Javascript使用低级编程语言(例如C ++)在后台执行这些操作。
Open your console and type window then press enter. You'll see most everything the Web API has to offer. This includes things like ajax calls, event listeners, the fetch API, and setTimeout. Javascript uses low level programming languages like C++ to perform these behind the scenes.
-案例
Let's look at a simple example, run this code your console:
console.log("first")
setTimeout(() => {
console.log("second")
}, 1000)
console.log("third")
-初步猜测结果(非译文内容)
控制台依次输出first-second-third
-测试验证
What did we get back?
first
third
undefined
second
-原理讲解(flag)
Feels odd, right? Well, let's break this down line by line:
console.log("first")
is on the stack first, so it gets printed. Next, the engine notices setTimeout, which isn't handled by Javascript and pushes it off to the WebAPI to be done asynchronously. The call stack moves on without caring about the code handed off to the Web APIs and console.log("three")
is printed.
Next, the Javascript engine's event loop kicks in, like a little kid asking "Are we there yet?" on a road trip. It starts firing, waiting for events to be pushed into it. Since the setTimeout
isn't finished, it returns undefined
, as the default, well because it hasn't been given the value yet. Once the callback finally does hits we get console.log("second")
printed.
-沙盒推荐 (flag)
There's a really good site that slows this all down and shows this happening.
I suggest playing around in this sandbox to help solidify your understanding. It helped me get a feel for how asynchronous code can work with Javascript being single threaded.
小记过去笔者@buuoltwo的最简理解:
- 单线程是JavaScript语言的一大特点,简单的说就是一个人同一时间只能做一件事情。
- 主线程处理同步任务
- 任务队列处理异步任务
- -任务队列是JS把异步任务挂起,做了个异步任务清单,
JS在跑完执行栈的同步任务后才把任务队列的异步任务推送给主线程