特集
» 2017年02月10日 05時00分 UPDATE

特集:HTML 5.1概説:HTML 5.1で追加されたHTMLフォームの検証メソッドとPromise関連の新機能 (2/3)

[かわさきしんじ,Insider.NET編集部]

EnqueueJob/NextJobメソッド

 「Changes」ページには、HTML 5.1での変更点が幾つか挙げられているが、このうち「<picture>要素とsrcset属性」「requestAnimationFrame API」については前回の記事で、「<details>要素と<summary>要素」「コンテキストメニュー」については「Dev Basics/Keyword HTML 5.1」で触れている。そこで次に「EnqueueJobとNextJob」について簡単に見てみよう。

 「enqueueJob and nextJob help explain Promise resolution in terms of microtasks」(マイクロタスクの観点からPromiseがどう解決されるのかを説明するのに役立つ)といわれてもなかなか分かりにくいのだが、これはHTML 5.1仕様とECMAScript仕様の齟齬を回避するための「willfull violation」(故意のJavaScript仕様違反)であり、主にブラウザ開発者に向けた変更点だと考えられる。

 つまり、現状のECMAScript仕様では、Promise関連の処理をWebブラウザで処理するのが難しいため、HTML 5.1の仕様ではECMAScript仕様を上書きしているということになる(ここではHTML 5.1でEnqueueJob/NextJobメソッドを定義し、ECMAScriptのそれらを上書きすることで、ブラウザ内でPromiseを素直に処理できるようにしていると筆者は読み取った)。

 実際、HTML 5.1の言語仕様の「7.1.3.7 ntegration with the JavaScript job queue」を見ると「Promiseの処理をJavaScriptの実行コンテキストスタックで何らかの順序で行うことに関して、一定の規則を示すために、JavaScriptの言語仕様ではJavaScriptのジョブとそのキューを抽象化したものを定義しているが、HTML 5.1の言語仕様の執筆時点では、JavaScriptのホスト環境としてHTMLを統合することを考えると、この仕様には柔軟性が足りていない」といったことが記述されている(筆者による意訳)。

 そして、EnqueueJobに関して、ユーザーエージェント(Webブラウザ)はECMAScriptの言語仕様ではなく、HTML 5.1の仕様に従わなければならず、これによりPromiseを処理するためのジョブをWebブラウザが保持するイベントループにキューイングして、適切に処理できるようになるとのことだ。

 うまくいかない場合を試してみるのは難しいことから、実際にChrome/Firefox/Edgeで動作するコードを書いてみた。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>HTML 5.1 Promise sample</title>
    <script>
    const a = [
      { n: 1, amount: 3000 },
      { n: 2, amount: 2000 },
      { n: 3, amount: 4000 },
      { n: 4, amount: 1000 }
    ];

    function sleepAsync(item) {
      return new Promise(
        function(resolve, reject) {
          window.setTimeout(function() {
            document.getElementById("output" + item.n).innerText = "resolved";
            resolve("resolved");
          }, item.amount)
        }
      )
    }

    window.onload = function() {
      const plist = a.map(sleepAsync);
      Promise.all(plist).then(
        function(msg) {
          document.getElementById("outputall").innerText = msg;
        }
      );
    }
    </script>
  </head>
  <body>
    <ol>
      <li> <p id="output1">start processing Promise.</p></li>
      <li> <p id="output2">start processing Promise.</p></li>
      <li> <p id="output3">start processing Promise.</p></li>
      <li> <p id="output4">start processing Promise.</p></li>
    </ol>
    <div><b>all promises status:</b> <span id="outputall"></span></div>
  </body>
</html>

Webブラウザ内でPromise操作を行うコード

 詳細な解説は割愛するが、上のコードでは4つのPromiseオブジェクトを作成している。これらのオブジェクトは1000ミリ秒、2000ミリ秒、3000ミリ秒、4000ミリ秒を待機した後で、自身に関連付けられている箇条書きの要素(idが「output」+「1〜4の番号」の<li>要素)に「resolved」と書き込むものだ。そして、4つのPromiseオブジェクトをまとめたもう1つのPromiseオブジェクトを「Promise.all」メソッドで作成し、全ての処理が完了したら、「all promises status」行に処理結果を表示するようになっている。

 実行途中の様子を以下に示す。

Webブラウザ内でのPromise操作 Webブラウザ内でのPromise操作

 このようなPromise処理をブラウザ内でも実行可能とするために、HTML 5.1では「あえてJavaScriptの言語仕様を上書き」しているということだ。

 なお、上で見た「willfull violation」という語についてはHTML 5.1の言語仕様の「1.5.2 Compliance with other specifications」で「HTML 5.1の言語仕様は、それ以外のさまざまな仕様と関連するが、残念ながら他の仕様とは矛盾する必要性が生じたときには、それらの仕様で定められている要件に違反することがある。違反がある部分については個々に『willfull violation』であることと、違反した理由が示される」(筆者による意訳)とある。EnqueueJob/NextJobはそうした「故意の違反」の1つである。

 なお、IE11では基本的には上記コードは実行できない。これはPromiseオブジェクトをIE11がサポートしていないからだ。

IE11ではPromiseが定義されていない IE11ではPromiseが定義されていない

 ただし、Promise.jsで配布されているpolyfillを読み込むことで実行可能だ(詳細は割愛)。

 次に、HTML 5.1で追加されたもう1つのPromise関連の新機能を見てみよう。

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。