8

解決のための質問ではなく、システムをよりよく理解するための質問

専門家!JavaScriptコードをjavascriptエンジンにフィードするたびに、javascriptエンジンによってすぐに実行されることを私は知っています。Engine のソースコードを見ていないので、以下のような質問がいくつかあります。

リモート サーバーから FILE_1.js と FILE_2.js という 2 つのファイルを読み込んでいるとします。また、FILE_2.js のコードは、FILE_1.js のコードの一部を必要としています。だから私は次のようにファイルを含めました、

<script type="text/javascript" src="FILE_1.js" ></script>
<script type="text/javascript" src="FILE_2.js" ></script>

うまくいけば、私はJavascript Engineが必要とすることをしました。残念ながら、FILE_1.js に 5000 KB のコードを記述しましたが、FILE_2.js には 5 KB のコードがあります。サーバーはマルチスレッドであるため、FILE_1.js が完了する前に FILE_2.js がブラウザに読み込まれます。

JavaScriptエンジンはこれをどのように処理しますか?

また、次のようにコードを FILE_2.js から inline-script タグに移動した場合、この依存関係を管理するために JavaScript エンジンが実行するアクションは何ですか?

<script type="text/javascript" src="FILE_1.js" ></script>
<script type="text/javascript" >
// Dependent code goes here
</script>

注:シングルスレッドの単一の単語の回答は期待していません。ブラウザまたはJavaScriptエンジンまたは一般的な人のいずれかでリクエストの発行を管理しているのは誰ですか? リクエスト/レスポンスが一般の人によって処理される場合、javascript エンジンはこれをどのように認識していますか?

4

1 に答える 1

12

コードの動作に関する回答を投稿するときは、常に次の 2 つの場所に移動するのが好きです。

  1. 仕様
  2. 実装

仕様:

DOM API では、スクリプトを次の順序で実行する必要があることを明示的に指定しています。

要素に src 属性があり、async 属性がなく、「force-async」フラグが設定されていない場合、要素は、できるだけ早く実行されるスクリプト のリストの最後に追加する必要があります。スクリプト アルゴリズムの準備が開始された時点で、script 要素の Document を使用します。

4.1 スクリプティングから。deferorasync属性を持つ前に、この規則の例外のリストを確認してください。これは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.

通常は、モジュール ローダーを使用することをお勧めします (スクリプトの挿入と実行を延期し、依存関係を正しく管理します)。

現時点では、BrowserifyRequireJSなどを使用するのが最善の方法です。将来的には、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);

素晴らしいので、仕様にあるように、解析された順に追加されていることがソース コードでわかります。

スクリプト ランナーの動作を見てみましょう。

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;
     }

そして、タイマーを使用して、準備ができたら (または何も保留されていない場合はすぐに) 1 つずつ起動します。

 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();
    }
于 2014-02-28T20:42:20.953 に答える