如果 Javascript 是单线程的,它是如何异步的
Javascript 是一种单线程语言。这意味着它有一个调用栈和一个内存堆。正如预期的那样,它按顺序执行代码,并且必须在执行下一段代码之前完成一段代码。它是同步的,但有时可能是有害的。例如,如果一个函数需要一段时间才能执行或必须等待某事,它会同时冻结所有内容。
发生这种情况的一个很好的例子是窗口警报功能。alert("Hello World")
在您点击 OK 并关闭警报之前,您根本无法与网页交互。你被困住了。
那么我们如何使用 Javascript 获取异步代码呢?
好吧,我们要感谢 Javascript 引擎(V8、Spidermonkey、JavaScriptCore 等),它有在后台处理这些任务的 Web API。调用堆栈识别 Web API 的函数并将它们交给浏览器处理。一旦浏览器完成了这些任务,它们就会返回并作为回调推送到堆栈中。
打开您的控制台并输入,window
然后按回车键。您将看到 Web API 所提供的大部分内容。这包括诸如 ajax 调用、事件侦听器、获取 API 和 setTimeout 之类的东西。Javascript 使用 C++ 等低级编程语言在幕后执行这些操作。
让我们看一个简单的例子,在你的控制台运行这段代码:
console.log("first")
setTimeout(() => {
console.log("second")
}, 1000)
console.log("third")
我们得到了什么?
第一
第三
未定义
第二
感觉很奇怪,对吧?好吧,让我们逐行分解:
console.log("first")
首先在堆栈上,所以它被打印出来。**接下来,引擎注意到 setTimeout,它不由 Javascript 处理,并将其推送到 WebAPI 以异步完成。**调用堆栈继续前进,而不关心移交给 Web API 的代码console.log("three")
并被打印出来。
接下来,Javascript 引擎的事件循环启动,就像一个小孩子问“我们到了吗?” 在一次公路旅行中。它开始触发,等待事件被推入其中。由于setTimeout
没有完成,它返回undefined
,作为默认值,因为它还没有被赋予值。一旦回调最终成功,我们就会被console.log("second")
打印出来。
有一个非常好的网站可以减慢这一切并展示这种情况。
我建议在这个沙盒中玩耍,以帮助巩固你的理解。它帮助我了解异步代码如何与单线程 Javascript 一起工作。
参考:https ://dev.to/bbarbour/if-javascript-is-single-threaded-how-is-it-asynchronous-56gd
https://stackoverflow.com/questions/51007636/how-javascript-single-threaded-and-asynchronous
- 原文作者:知识铺
- 原文链接:https://geek.zshipu.com/post/javascript/%E5%A6%82%E6%9E%9C-Javascript-%E6%98%AF%E5%8D%95%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%AE%83%E6%98%AF%E5%A6%82%E4%BD%95%E5%BC%82%E6%AD%A5%E7%9A%84/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com