JavaScript执行引擎未指定?

Edw*_*rzo 11 javascript multithreading asynchronous node.js ecmascript-5

我最近开始学习JavaScript.我一直在用Node.jsAngular创建应用程序几个月了.

令我困惑的一个主要方面是如何在JavaScript中编写异步代码,我不必担心线程同步,竞争条件等问题.

所以,我发现了一些有趣的文章([1],[2]),这些文章解释了我如何能够保证我编写的任何代码片段当时都会由一个线程执行.最重要的是,我的所有异步代码都被安排在事件循环中的某个时刻执行.这听起来非常类似于OS调度程序可以在具有单个处理器的机器中工作,其中每个进程被安排在有限的时间内使用处理器,给我们假的并行感.回调就像中断.

文章没有提供任何特定的参考,所以我认为关于JavaScript执行引擎如何工作的最佳来源当然应该是语言规范,所以我给了我最新的EcmaScript 5.1副本.

令我惊讶的是,我发现在那里没有指定这种执行行为.怎么会?这看起来像是在浏览器和节点中的所有JavaScript执行引擎中完成的基本设计选择.有趣的是,我无法找到为任何特定引擎指定的地方.事实上,我不知道人们如何发现这是事情的工作方式,在上面引用的书籍和博客中如此明确地肯定.

所以,我有一套我认为有趣的问题.我很感激任何提供见解,评论或简单参考的答案,指出我正确的方向,以了解以下内容:

  • 由于EcmaScript没有指定JavaScript执行引擎应该使用事件循环,为什么JavaScript的实现似乎以这种方式工作,不仅在浏览器中,而且在Node.js中?
  • 这是否意味着我可以实现一个与EcmaScript兼容的新JavaScript引擎,它实际上提供了具有诸如同步锁,条件等功能的真正多线程功能?
  • 如果我想执行一个强大的CPU绑定任务,这个使用事件循环的执行模型是否阻止我利用多核?我的意思是,我可以肯定地将任务划分为块(如其中一篇文章中所述),但这仍然是串行执行的,而不是并行执行.那么,JavaScript引擎如何利用多核来运行我的代码呢?
  • 您是否知道任何其他信誉良好的来源,其中任何特定的JavaScript引擎实现的这种行为是正式指定的?
  • 如果我们不能假设有关执行环境的一些事情,那么代码如何在库和引擎之间移植?

看起来有太多问题,也许这个帖子太宽泛而无法回答.如果它被关闭,我将尝试在不同的线程中询问它们.但它们都围绕着这样一个事实:我想更好地理解为什么JavScript和Node是用事件循环设计的,如果在某处(除了浏览器源代码)指定了我可以阅读并更深入地了解设计和决策在这里,更重要的是,要确切地知道人们撰写有关它的书籍和帖子的信息来源.

use*_*109 6

您做出的某些假设/弱参考会引导您得出这个结论.他们之中有一些是:

  1. ECMAScript ECMA-XXX vs JavaScript与JavaScriptEngine:

    ECMAscript是ECMA International提供的语言规范.JavaScript是最广泛使用的符合ECMAscript的Web语言.在大多数情况下,ECMAScript和JavaScript是同义词(记住有ActionScript).JavaScriptEngine是JavaScript语言代码的实现(解释器).这是一个以肉体为基础的程序,与ECMAScript不同的是骨头工作,它只描述了JavaScript的最终目标和行为,而JavaScript则是使用ECMAScript标准的代码.您会发现引擎不仅仅符合ECMAScript标准.它们处于规范/实施范围的末端.示例是ECMA-262/JavaScript/V8.

  2. 浏览器中的事件循环与node.JS中的事件循环(JSEngine vs JSEnvironment):

    这看起来像是在浏览器和节点中的所有JavaScript执行引擎中完成的基本设计选择.

    如果您使用node.JS,则可能使用了核心库fs/net/http.这些使用事件发射器,它们与libuv提供的事件循环相连.这是JavaScriptEngine V8的扩展,形成node.JS平台.这里的事件循环涉及线程,套接字,文件或抽象请求等对象.但事件并非源于此.它首先在浏览器中使用.浏览器实现了一个DOM,它需要事件来处理HTML元素.请参阅DOM 规范和为Mozilla实现的规范.他们使用事件并要求在JSEngine之上构建一个事件循环以供浏览器使用.Chrome将DOM界面添加到它嵌入的V8引擎中.

    是的,您会觉得这很常见,因为所有浏览器都有必要的DOM API.节点开发人员在libuv的帮助下将这种新颖的事务处理提交到服务器,libuv为服务器上所需的低级操作提供非阻塞,异步抽象.如前所述,并非所有服务器框架都使用事件循环.以Rhino为例,它实际上使用Java Classes作为文件,套接字(一切).如果您实际使用核心Java IO,则文件操作是同步的.

现在按顺序回答你的问题:

  • 在上面第2点解释

  • 是的你可以.看看Rhino,还有很多其他的.它可能在节点中,但节点适合作为高性能的Web服务器,并且可能违背其禅宗.

  • 就像我说的那样,事件循环位于JSEngine上.这是一种设计模式,最适合IO.多线程设计在高CPU负载下工作得更好.如果要在node.JS中使用多个核心,请查看群集模块.对于浏览器,您有webworkers

  • 这因发动机而异.它是如何嵌入的.浏览器将具有DOM并因此具有事件循环.服务器可以变化.检查他们的规格.

  • 对于浏览器,可以在很大程度上使它们在它们之间移植.对服务器没有承诺.


vku*_*kin 5

  1. 事件循环与javascript本身没有任何关系,它是环境的一部分,而不是js引擎。由于 javascript 主要是为了操作用户界面而设计的,因此它大量与事件循环一起使用。但事件循环是 UI 实现的一部分,不仅在 JavaScript 中,在任何语言中都是如此。

  2. 是的你可以。但它不仅仅是引擎,更像是环境/平台。我认为(但不太确定)你可以在 Rhino 中使用线程和相关的东西。

  3. 是的,它确实。在节点中,这通常可以通过生成更多进程来解决,在浏览器中,您可以使用 WebWorkers。

  4. 我无法想象比规范更好的来源。如果某些东西不存在,那么它只是不是 javascript(又名 EcmaScript)的一部分

  • @EdwinDalorzo 我只是说这不是语言级别的事情。例如,C 也没有定义任何并发原语(至少在 C11 之前)。因此您可以使用基于事件或基于线程的并发。有些语言(例如Java)拥有庞大的标准库,但这只是另一种方法,维护成本很高。ES 规范紧凑且重点突出。事件循环相关的东西只是 Web api 的实现细节。如果您想了解如何实现它,请查看 Nodes libuv。它提供了事件循环的 C 实现,并且与节点的其他部分真正解耦。 (2认同)