1. 8.6 タイマー
    2. 8.7 マイクロタスクのキュー
    3. 8.8 ユーザープロンプト
      1. 8.8.1 単純ダイアログ
      2. 8.8.2 印刷

8.6 タイマー

setTimeout()setInterval()メソッドは、著者がタイマーベースのコールバックをスケジュールできるようにする。

handle = self.setTimeout(handler [, timeout [, ...arguments ] ])

setTimeout

Support in all current engines.

Firefox1+Safari1+Chrome1+
Opera4+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android4+Safari iOS1+Chrome Android18+WebView Android1+Samsung Internet1.0+Opera Android10.1+

timeoutミリ秒後にhandlerを実行するためにタイムアウトをスケジュールする。すべてのargumentsは直接handlerに渡される。

handle = self.setTimeout(code [, timeout ])

timeoutミリ秒後にcodeを実行するためにタイムアウトをスケジュールする。

self.clearTimeout(handle)

clearTimeout

Support in all current engines.

Firefox1+Safari4+Chrome1+
Opera4+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android4+Safari iOS1+Chrome Android18+WebView Android37+Samsung Internet1.0+Opera Android10.1+

handleで識別されるsetTimeout()またはsetInterval()で設定されたタイムアウトをキャンセルする。

handle = self.setInterval(handler [, timeout [, ...arguments ] ])

setInterval

Support in all current engines.

Firefox1+Safari1+Chrome1+
Opera4+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android4+Safari iOS1+Chrome Android18+WebView Android1+Samsung Internet1.0+Opera Android10.1+

timeoutミリ秒ごとにhandlerを実行するためにタイムアウトをスケジュールする。すべてのargumentsは直接handlerに渡される。

handle = self.setInterval(code [, timeout ])

timeoutミリ秒ごとにcodeを実行するためにタイムアウトをスケジュールする。

self.clearInterval(handle)

clearInterval

Support in all current engines.

Firefox1+Safari1+Chrome1+
Opera4+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android4+Safari iOS1+Chrome Android18+WebView Android37+Samsung Internet1.0+Opera Android10.1+

handleで識別されるsetInterval()またはsetTimeout()で設定されたタイムアウトをキャンセルする。

タイマーは入れ子にすることができる。しかし、5つのそのようなネストされたタイマー後に、間隔は少なくとも4ミリ秒であることが強制される。

このAPIは、タイマーがスケジュールどおり正確に動作することを保証しない。CPU負荷やその他のタスクなどによる遅延が予想される。

Objects that implement the WindowOrWorkerGlobalScope mixin have a list of active timers. Each entry in this lists is identified by a number, which must be unique within the list for the lifetime of the object that implements the WindowOrWorkerGlobalScope mixin.


The setTimeout(handler, timeout, ...arguments) method must return the value returned by the timer initialization steps, passing them the method's arguments, the object on which the method for which the algorithm is running is implemented (a Window or WorkerGlobalScope object) as the method context, and the repeat flag set to false.

The setInterval(handler, timeout, ...arguments) method must return the value returned by the timer initialization steps, passing them the method's arguments, the object on which the method for which the algorithm is running is implemented (a Window or WorkerGlobalScope object) as the method context, and the repeat flag set to true.

The clearTimeout(handle) and clearInterval(handle) methods must clear the entry identified as handle from the list of active timers of the WindowOrWorkerGlobalScope object on which the method was invoked, if any, where handle is the argument passed to the method. (If handle does not identify an entry in the list of active timers of the WindowOrWorkerGlobalScope object on which the method was invoked, the method does nothing.)

Because clearTimeout() and clearInterval() clear entries from the same list, either method can be used to clear timers created by setTimeout() or setInterval().


The timer initialization steps, which are invoked with some method arguments, a method context, a repeat flag which can be true or false, and optionally (and only if the repeat flag is true) a previous handle, are as follows:

  1. Let method context proxy be method context if that is a WorkerGlobalScope object, or else the WindowProxy that corresponds to method context.

  2. If previous handle was provided, let handle be previous handle; otherwise, let handle be an implementation-defined integer that is greater than zero that will identify the timeout to be set by this call in the list of active timers.

  3. If previous handle was not provided, add an entry to the list of active timers for handle.

  4. Let callerRealm be the current Realm Record, and calleeRealm be method context's JavaScript realm.

  5. Let initiating script be the active script.

  6. Assert: initiating script is not null, since this algorithm is always called from some script.

  7. Let task be a task that runs the following substeps:

    1. If the entry for handle in the list of active timers has been cleared, then abort these steps.

    2. Run the appropriate set of steps from the following list:

      If the first method argument is a Function

      Invoke the Function. Use the third and subsequent method arguments (if any) as the arguments for invoking the Function. Use method context proxy as the callback this value. If this throws an exception, catch it, and report the exception.

      そうでなければ
      1. Perform HostEnsureCanCompileStrings(callerRealm, calleeRealm). If this throws an exception, catch it, report the exception, and abort these steps.

      2. Let script source be the first method argument.

      3. Let settings object be method context's environment settings object.

      4. Let base URL be initiating script's base URL.

      5. Assert: base URL is not null, as initiating script is a classic script or a JavaScript module script.

      6. Let fetch options be a script fetch options whose cryptographic nonce is initiating script's fetch options's cryptographic nonce, integrity metadata is the empty string, parser metadata is "not-parser-inserted", credentials mode is initiating script's fetch options's credentials mode, and referrer policy is initiating script's fetch options's referrer policy.

        The effect of these options ensures that the string compilation done by setTimeout() and setInterval() behaves equivalently to that done by eval(). That is, module script fetches via import() will behave the same in both contexts.

      7. Let script be the result of creating a classic script given script source, settings object, base URL, and fetch options.

      8. Run the classic script script.

    3. If the repeat flag is true, then call timer initialization steps again, passing them the same method arguments, the same method context, with the repeat flag still set to true, and with the previous handle set to handler.

  8. Let timeout be the second method argument.

  9. If the currently running task is a task that was created by this algorithm, then let nesting level be the task's timer nesting level. Otherwise, let nesting level be zero.

    The task's timer nesting level is used both for nested calls to setTimeout(), and for the repeating timers created by setInterval(). (Or, indeed, for any combination of the two.) In other words, it represents nested invocations of this algorithm, not of a particular method.

  10. If timeout is less than 0, then set timeout to 0.

  11. If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4.

  12. Increment nesting level by one.

  13. Let task's timer nesting level be nesting level.

  14. Return handle, and then continue running this algorithm in parallel.

  15. If method context is a Window object, wait until the Document associated with method context has been fully active for a further timeout milliseconds (not necessarily consecutively).

    Otherwise, method context is a WorkerGlobalScope object; wait until timeout milliseconds have passed with the worker not suspended (not necessarily consecutively).

  16. Wait until any invocations of this algorithm that had the same method context, that started before this one, and whose timeout is equal to or less than this one's, have completed.

    Argument conversion as defined by Web IDL (for example, invoking toString() methods on objects passed as the first argument) happens in the algorithms defined in Web IDL, before this algorithm is invoked.

    So for example, the following rather silly code will result in the log containing "ONE TWO ":

    var log = '';
    function logger(s) { log += s + ' '; }
    
    setTimeout({ toString: function () {
      setTimeout("logger('ONE')", 100);
      return "logger('TWO')";
    } }, 100);
  17. Optionally, wait a further implementation-defined length of time.

    This is intended to allow user agents to pad timeouts as needed to optimize the power usage of the device. For example, some processors have a low-power mode where the granularity of timers is reduced; on such platforms, user agents can slow timers down to fit this schedule instead of requiring the processor to use the more accurate mode with its associated higher power usage.

  18. Queue a global task on the timer task source given method context to run task.

    Once the task has been processed, if the repeat flag is false, it is safe to remove the entry for handle from the list of active timers (there is no way for the entry's existence to be detected past this point, so it does not technically matter one way or the other).

遅延なく背中合わせに数ミリ秒のタスクを実行するために、飢えたユーザーインターフェイスを避けるために(およびCPUを占有するためのスクリプトを殺すブラウザーを避けるために)ブラウザーに戻って従いつつ、作業を実行する前の簡単なキューの次のタイマー:

function doExpensiveWork() {
  var done = false;
  // ...
  // this part of the function takes up to five milliseconds
  // set done to true if we're done
  // ...
  return done;
}

function rescheduleWork() {
  var handle = setTimeout(rescheduleWork, 0); // preschedule next iteration
  if (doExpensiveWork())
    clearTimeout(handle); // clear the timeout if we don't need it
}

function scheduleWork() {
  setTimeout(rescheduleWork, 0);
}

scheduleWork(); // queues a task to do lots of work

8.7 マイクロタスクのキュー

queueMicrotask

Support in all current engines.

Firefox69+Safari12.1+Chrome71+
Opera58+Edge79+
Edge (Legacy)NoInternet ExplorerNo
Firefox Android79+Safari iOS12.2+Chrome Android71+WebView Android71+Samsung Internet10.0+Opera Android50+
self.queueMicrotask(callback)

指定されたcallbackを実行するためのマイクロタスクキューに入れる

queueMicrotask(callback)メソッドは、callback呼び出すためにマイクロタスクをキューに入れ、かつcallbackが例外を投げた場合は例外を報告しなければならない。

queueMicrotask()メソッドは、著者がマイクロタスクキューでコールバックをスケジュールすることを可能にする。This allows their code to run once the JavaScript execution context stack is next empty, which happens once all currently executing synchronous JavaScript has run to completion. This doesn't yield control back to the event loop, as would be the case when using, for example, setTimeout(f, 0).

著者は、大量のマイクロタスクをスケジュールすることが、大量の同期コードを実行するのと同じパフォーマンスの低下があることに注意する必要がある。 Both will prevent the browser from doing its own work, such as rendering. 多くの場合、requestAnimationFrame()またはrequestIdleCallback()の方がよい選択である。 特に、次のレンダリングサイクルの前にコードを実行することが目標である場合、それはrequestAnimationFrame()の目的である。

As can be seen from the following examples, the best way of thinking about queueMicrotask() is as a mechanism for rearranging synchronous code, effectively placing the queued code immediately after the currently executing synchronous JavaScript has run to completion.

queueMicrotask() 使用する最も一般的な理由は、情報が同期的に利用できる場合でも、過度の遅延を発生させることなく、一貫した順序を作成することである。

たとえば、以前にロードされたデータの内部キャッシュも維持する、loadイベントを発生させるカスタム要素について考えてみる。ナイーブな実装は次のようになるだろう:

MyElement.prototype.loadData = function (url) {
  if (this._cache[url]) {
    this._setData(this._cache[url]);
    this.dispatchEvent(new Event("load"));
  } else {
    fetch(url).then(res => res.arrayBuffer()).then(data => {
      this._cache[url] = data;
      this._setData(data);
      this.dispatchEvent(new Event("load"));
    });
  }
};

しかし、このナイーブな実装には、ユーザーに一貫性のない動作が発生するという問題がある。たとえば、次のようなコードは

element.addEventListener("load", () => console.log("loaded"));
console.log("1");
element.loadData();
console.log("2");

"1, 2, loaded"(データをフェッチする必要がある場合)を記録することもあれば、"1, loaded, 2"(データがすでにキャッシュされている場合)を記録することもある。同様に、loadData()の呼び出し後、データが要素に設定されているかどうかは一貫性がない。

一貫した順序を取得するためには、queueMicrotask()を使用できる:

MyElement.prototype.loadData = function (url) {
  if (this._cache[url]) {
    queueMicrotask(() => {
      this._setData(this._cache[url]);
      this.dispatchEvent(new Event("load"));
    });
  } else {
    fetch(url).then(res => res.arrayBuffer()).then(data => {
      this._cache[url] = data;
      this._setData(data);
      this.dispatchEvent(new Event("load"));
    });
  }
};

By essentially rearranging the queued code to be after the JavaScript execution context stack empties, this ensures a consistent ordering and update of the element's state.

queueMicrotask()のもう1つの興味深い使用法は、 複数の呼び出し元による作業の調整されていない"バッチ処理"を可能にすることである。たとえば、できるだけ早くどこかにデータを送信したいが、簡単に回避できる場合は、 複数のネットワークリクエストを行いたくないライブラリ関数について考えてみる。このバランスをとる1つの方法は次のようになる:

const queuedToSend = [];

function sendData(data) {
  queuedToSend.push(data);

  if (queuedToSend.length === 1) {
    queueMicrotask(() => {
      const stringToSend = JSON.stringify(queuedToSend);
      queuedToSend.length = 0;

      fetch("/endpoint", stringToSend);
    });
  }
}

With this architecture, multiple subsequent calls to sendData() within the currently executing synchronous JavaScript will be batched together into one fetch() call, but with no intervening event loop tasks preempting the fetch (as would have happened with similar code that instead used setTimeout()).

8.8 ユーザープロンプト

8.8.1 単純ダイアログ

window.alert(message)

Window/alert

Support in all current engines.

Firefox1+Safari1+Chrome1+
Opera3+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android4+Safari iOS1+Chrome Android18+WebView Android1+Samsung Internet1.0+Opera Android10.1+

指定されたメッセージを持つモーダルアラートを表示し、それを命令するユーザーに対して待機する。

result = window.confirm(message)

Window/confirm

Support in all current engines.

Firefox1+Safari1+Chrome1+
Opera3+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android4+Safari iOS1+Chrome Android18+WebView Android1+Samsung Internet1.0+Opera Android10.1+

与えられたメッセージとともにモーダルOK/Cancelプロンプトを表示し、それを命令するユーザーに対して待機し、ユーザーがOKをクリックした場合はtrueを返し、ユーザーがCancelをクリックする場合はfalseを返す。

result = window.prompt(message [, default])

Window/prompt

Support in all current engines.

Firefox1+Safari1+Chrome1+
Opera3+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android4+Safari iOS1+Chrome Android18+WebView Android1+Samsung Internet1.0+Opera Android10.1+

与えられたメッセージとともにモーダルテキストコントロールプロンプトを表示し、ユーザーがそれを閉じるのを待ち、ユーザーが入力した値を返す。ユーザーがプロンプトをキャンセルした場合、代わりにnullを返す。2番目の引数が存在する場合、指定された値がデフォルトとして使用される。

メディアデータを読み込むメディア要素のような、タスクまたはマイクロタスクに依存するロジックは、このメソッドが発動されるときに延期される。

The alert() and alert(message) method steps are:

  1. If we cannot show simple dialogs for this, then return.

  2. If the method was invoked with no arguments, then let message be the empty string; otherwise, let message be the method's first argument.

  3. Set message to the result of normalizing newlines given message.

  4. Set message to the result of optionally truncating message.

  5. Show message to the user, treating U+000A LF as a line break.

  6. Optionally, pause while waiting for the user to acknowledge the message.

This method is defined using two overloads, instead of using an optional argument, for historical reasons. The practical impact of this is that alert(undefined) is treated as alert("undefined"), but alert() is treated as alert("").

The confirm(message) method steps are:

  1. If we cannot show simple dialogs for this, then return false.

  2. Set message to the result of normalizing newlines given message.

  3. Set message to the result of optionally truncating message.

  4. Show message to the user, treating U+000A LF as a line break, and ask the user to respond with a positive or negative response.

  5. Pause until the user responds either positively or negatively.

  6. If the user responded positively, return true; otherwise, the user responded negatively: return false.

The prompt(message, default) method steps are:

  1. If we cannot show simple dialogs for this, then return null.

  2. Set message to the result of normalizing newlines given message.

  3. Set message to the result of optionally truncating message.

  4. Set default to the result of optionally truncating default.

  5. Show message to the user, treating U+000A LF as a line break, and ask the user to either respond with a string value or abort. The response must be defaulted to the value given by default.

  6. Pause while waiting for the user's response.

  7. If the user aborts, then return null; otherwise, return the string that the user responded with.

To optionally truncate a simple dialog string s, return either s itself or some string derived from s that is shorter. User agents should not provide UI for displaying the elided portion of s, as this makes it too easy for abusers to create dialogs of the form "Important security alert! Click 'Show More' for full details!".

For example, a user agent might want to only display the first 100 characters of a message. Or, a user agent might replace the middle of the string with "…". These types of modifications can be useful in limiting the abuse potential of unnaturally large, trustworthy-looking system dialogs.

We cannot show simple dialogs for a Window window when the following algorithm returns true:

  1. If the active sandboxing flag set of window's associated Document has the sandboxed modals flag set, then return true.

  2. If window's relevant settings object's origin and window's relevant settings object's top-level origin are not same origin-domain, then return true.

  3. If window's relevant agent's event loop's termination nesting level is nonzero, then optionally return true.
  4. Optionally, return true. (For example, the user agent might give the user the option to ignore all modal dialogs, and would thus abort at this step whenever the method was invoked.)

  5. falseを返す。

8.8.2 印刷

Window/print

Support in all current engines.

Firefox1+Safari1.1+Chrome1+
Opera6+Edge79+
Edge (Legacy)12+Internet Explorer5+
Firefox AndroidNoSafari iOS1+Chrome Android18+WebView Android1+Samsung Internet1.0+Opera Android10.1+
window.print()

ページを印刷するようユーザーに指示する。

The print() method steps are:

  1. Let document be this's associated Document.

  2. If document is not fully active, then return.

  3. If document's unload counter is greater than 0, then return.

  4. If document is ready for post-load tasks, then run the printing steps for document.

  5. Otherwise, set document's print when loaded flag.

User agents should also run the printing steps whenever the user asks for the opportunity to obtain a physical form (e.g. printed copy), or the representation of a physical form (e.g. PDF copy), of a document.

The printing steps for a Document document are:

  1. The user agent may display a message to the user or return (or both).

    For instance, a kiosk browser could silently ignore any invocations of the print() method.

    For instance, a browser on a mobile device could detect that there are no printers in the vicinity and display a message saying so before continuing to offer a "save to PDF" option.

  2. If the active sandboxing flag set of document has the sandboxed modals flag set, then return.

    If the printing dialog is blocked by a Document's sandbox, then neither the beforeprint nor afterprint events will be fired.

  3. The user agent must fire an event named beforeprint at the relevant global object of document, as well as any child browsing contexts in it.

    The beforeprint event can be used to annotate the printed copy, for instance adding the time at which the document was printed.

  4. The user agent should offer the user the opportunity to obtain a physical form (or the representation of a physical form) of document. The user agent may wait for the user to either accept or decline before returning; if so, the user agent must pause while the method is waiting. Even if the user agent doesn't wait at this point, the user agent must use the state of the relevant documents as they are at this point in the algorithm if and when it eventually creates the alternate form.

  5. The user agent must fire an event named afterprint at the relevant global object of document, as well as any child browsing contexts in it.

    The afterprint event can be used to revert annotations added in the earlier event, as well as showing post-printing UI. For instance, if a page is walking the user through the steps of applying for a home loan, the script could automatically advance to the next step after having printed a form or other.