HIL*_*EEN 8 javascript javascript-engine
问题不是解决方案,更好地了解系统的问题
专家!我知道每当你将javascript代码提供给javascript引擎时,它将立即通过javascript引擎执行.既然,我还没有看过Engine的源代码,我的问题如下,
我们假设我从远程服务器加载了几个文件,即FILE_1.js和FILE_2.js.并且FILE_2.js中的代码需要FILE_1.js中的一些代码.所以我已经包含如下文件,
<script type="text/javascript" src="FILE_1.js" ></script>
<script type="text/javascript" src="FILE_2.js" ></script>
Run Code Online (Sandbox Code Playgroud)
所以希望,我已经完成了Javascript引擎所需的工作.不幸的是,我在FILE_1.js中编写了5000KB的代码,但是我在FILE_2.js中有5KB的代码.由于服务器是多线程的,因此在FILE_1.js完成之前,FILE_2.js将被加载到我的浏览器中.
javascript引擎如何处理这个?
如果将代码从FILE_2.js移动到内联脚本标记,如下所示,javascript引擎管理此依赖项的操作是什么?
<script type="text/javascript" src="FILE_1.js" ></script>
<script type="text/javascript" >
// Dependent code goes here
</script>
Run Code Online (Sandbox Code Playgroud)
注意:我不期待单个单词回答Single Threaded.我只想知道谁管理发布请求浏览器或javascript引擎或普通人?如果请求/响应是由普通人处理的,那么javascript引擎如何知道这一点?
Ben*_*aum 11
当我发布关于代码行为的答案时,我总是喜欢去两个地方:
DOM API显式指定脚本必须按顺序执行:
如果元素具有src属性,没有async属性,并且没有设置"force-async"标志 元素必须添加到脚本列表的末尾,这些脚本将按顺序执行,并尽快关联在准备脚本算法开始时使用脚本元素的Document.
从4.1脚本编写.请在检查此规则的例外列表之前 - 具有defer或async属性.这在4.12.1.15中有详细说明.
这是有道理的,想象一下:
//FILE_1.js
var trololo = "Unicorn";
....
// 1 million lines later
trololo = "unicorn";
var message = "Hello World";
//FILE_2.js
alert(message); // if file 1 doesn't execute first, this throws a reference error.
Run Code Online (Sandbox Code Playgroud)
通常最好使用模块加载器(这将推迟脚本插入和执行,并将正确地为您管理依赖项).
目前,最好的方法是使用Browserify或RequireJS之类的东西.将来,我们将能够使用ECMAScript 6模块.
嗯,你提到它,我无法抗拒.因此,如果我们检查Chromium闪烁源(在WebKit中仍然类似):
bool ScriptLoader::prepareScript(const TextPosition& scriptStartPosition,
LegacyTypeSupport supportLegacyTypes)
{
.....
} else if (client->hasSourceAttribute() && // has src attribute
!client->asyncAttributeValue() &&// and no `async` or `defer`
!m_forceAsync // and it was not otherwise forced
) { // - woah, this is just like the spec
m_willExecuteInOrder = true; // tell it to execute in order
contextDocument->scriptRunner()->queueScriptForExecution(this,
m_resource,
ScriptRunner::IN_ORDER_EXECUTION);
Run Code Online (Sandbox Code Playgroud)
很好,所以我们可以在源代码中看到它按解析顺序添加它们 - 就像规范所说的那样.
让我们看一下脚本运行器的作用:
void ScriptRunner::queueScriptForExecution(ScriptLoader* scriptLoader,
ResourcePtr<ScriptResource> resource,
ExecutionType executionType){
.....
// Adds it in the order of execution, as we can see, this just
// adds it to a queue
case IN_ORDER_EXECUTION:
m_scriptsToExecuteInOrder.append(PendingScript(element, resource.get()));
break;
}
Run Code Online (Sandbox Code Playgroud)
并且,使用计时器,它会在准备好时逐个触发它们(或者如果没有任何待处理的话立即触发):
void ScriptRunner::timerFired(Timer<ScriptRunner>* timer)
{
...
scripts.swap(m_scriptsToExecuteSoon);
for (size_t i = 0; i < size; ++i) {
....
//fire!
toScriptLoaderIfPossible(element.get())->execute(resource);
m_document->decrementLoadEventDelayCount();
}
Run Code Online (Sandbox Code Playgroud)