reason

約束の拒絶 (JavaScript)

仕様書

イベント

[49] 約束を扱う場合、履行時の処理を記述するのは普通のことで基本ですが、 拒絶時の処理は怠りがちです。 (例外投げられた処理を怠りがちなのと同じです。)

真に異常で通常なら起こり得ない問題のため拒絶時の処理を敢えて省くこともあれば、 失敗することもあるので拒絶時の処理を指定しなければならないのに漏れてしまった場合もあります。

どちらの場合でも、せめて開発者コンソールでは気づきたいですし、 例外に対する error イベントのようにスクリプト側で検知したいこともあります。

[50] そのため、約束拒絶されて処理されていないことを通知するイベントが用意されています。


[37] 約束拒絶され、それが処理されないままの時は、 unhandledrejection イベント大域オブジェクト発火されます。

[47] このイベントは、例外における error イベントに相当するものです。

[53] このイベント取消可能です。取消された場合、 開発者コンソールには何も表示されません。 取消されていない場合、拒絶について開発者コンソールに表示されます。


[38] unhandledrejection イベント発火された後から処理が追加された場合には、 rejectionhandled イベント大域オブジェクト発火されます。 unhandledrejection イベントイベントハンドラーで処理が追加された場合にはこのイベント発火されませんが、 それよりも後に処理が追加された場合に、発火されます。

[52] unhandledrejection発火するかどうかの判定は、 約束拒絶されてからわりとすぐに (マイクロタスク処理後に) 行われます。しかし約束をずっと保持しておいて、 しばらく経ってから処理が追加される可能性は残ります。 その場合に unhandledrejection イベントで把握できます。 ただし unhandledrejection イベント発火されることは保証されません。

[42] PromiseRejectionEvent インターフェイス >>5 は、 rejectionhandled/unhandledrejection イベントと共に用いられます。 文書環境ワーカー環境晒されています >>5

[44] PromiseRejectionEvent インターフェイスは、 他の Event インターフェイス同様のコンストラクターを持ちます >>5。 初期化のための辞書PromiseRejectionEventInit です >>5

[43] PromiseRejectionEvent インターフェイスは、 Event インターフェイス継承しています >>5PromiseRejectionEventInit 辞書は、 EventInit 辞書継承しています >>5

[34] PromiseRejectionEvent インターフェイスpromise IDL属性は、 当該通知の約束を表すもので、任意の Promise を値として持つ読み取り専用属性です。 取得器は本イベントオブジェクトについて指定された値を返さなければなりません>>5

[36] PromiseRejectionEvent インターフェイスreason IDL属性は、 当該約束拒絶理由を表すもので、任意値を持つ読み取り専用属性です。 取得器は本イベントオブジェクトについて指定された値を返さなければなりません>>5

[35] つまり、 catch で指定された関数引数として受け取るであろう値となります。

処理

約束

[25] 約束は、内部スロット PromiseIsHandled を持ちます >>24

[28] この値は、 Promise コンストラクターに初期化されます。

[32] thenawaitに設定されます。

[64] ReadableStreamWritableStream の処理でもに設定されることがあります。

[39] この値がの時に、 HostPromiseRejectionTracker が実行されます。


[55] HostPromiseRejectionTracker は、 ホスト環境定義の内部操作として JavaScript仕様書で定義されているものです >>54

[56] この操作は、引数として約束操作を与えられます >>54操作の値は、 reject または handle のいずれかです >>54


[59] 操作 reject は、約束約束ハンドラーの登録されていない状態で拒絶された時、 実行されます >>54

[62] Web では、次のようにしなければなりません >>5

  1. [21] 走っているスクリプト設定群オブジェクトこれから通知する拒絶された約束リストに、約束を追加します。

[51] この処理は拒絶時に PromiseIsHandledの場合に、実行されます。 拒絶は1回しか起こらないため、この処理も1回しか呼び出されません。 操作handle で呼び出された後にこちらの処理が呼び出されることもありません。


[60] 操作 handle は、 約束約束拒絶されているところ、ハンドラーが初めて追加された時、 実行されます >>54

[20] Web では、 次のようにしなければなりません >>5

  1. [22] 設定群オブジェクトを、走っているスクリプト設定群オブジェクトに設定します。
  2. [26] 設定群オブジェクトこれから通知する拒絶された約束リスト約束が含まれている場合、
    1. [27] 設定群オブジェクトこれから通知する拒絶された約束リストから約束を削除します。
  3. [29] それ以外で、設定群オブジェクト未決拒絶された約束弱集合約束が含まれている場合、
    1. [30] 設定群オブジェクト未決拒絶された約束弱集合から約束を削除します。
    2. [31] タスクをキューに追加します。
      処理
      1. [33] イベントを発火します。
        対象
        設定群オブジェクト大域オブジェクト
        インターフェイス
        PromiseRejectionEvent
        rejectionhandled
        trusted
        bubbles
        取消可能
        promise
        約束
        reason
        約束PromiseResult の値
      タスク源
      DOM操作タスク源

[63] この処理は then から呼び出されます。 PromiseIsHandledの時に呼び出されますが、 本処理の直後にに設定されるため、 本処理が呼び出されるのは高々1回です。 本処理が呼び出されるのは既に拒絶されている場合のみですから、 必ず操作 reject で1回呼び出された後になります。

環境設定群オブジェクト

[4] 環境設定群オブジェクトは、 これから通知する拒絶された約束リスト (about-to-be-notified rejected promises list) を持ちます >>2約束拒絶され、処理が追加されていない場合、このリストに約束が追加されていきます。 処理が追加されると、このリストから約束は削除されます。 最終的に残った約束について、 unhandledrejection イベント発火されます。

[3] 環境設定群オブジェクトは、 未決拒絶された約束弱集合 (outstanding rejected promises weak set) を持ちます >>2。この弱集合からその構成要素への参照は、 強参照であってはなりません >>2。 実装はサイズを制限しても構いません (例えば溢れるなら古いものを削除して構いません) >>2unhandledrejection イベント発火された約束は、 イベントハンドラーでも処理が追加されないままの場合、 このリストに追加されます。 処理が追加された時、このリストに約束が含まれていれば、 rejectionhandled イベント発火されます。

[6] 環境設定群オブジェクト設定群オブジェクト拒絶された約束について通知 (notify about rejected promises) は、 次のようにしなければなりません >>5

  1. [7] リストを、設定群オブジェクトこれから通知する拒絶された約束リストの複製に設定します。
  2. [9] リストが空なら、ここで停止します。
  3. [8] 設定群オブジェクトこれから通知する拒絶された約束リストを、空にします。
  4. [10] 次のようなタスクタスクキューに追加します。
    [11] タスク
    タスク源
    ?
    処理
    1. [12] リスト内の各約束 p について、
      1. [13] pPromiseIsHandledなら、 次の約束に進みます。
      2. [14] 新しいイベントイベント発火します。
        [15] イベント
        イベント型
        unhandledrejection
        インターフェイス
        PromiseRejectionEvent
        trusted
        bubbles
        取消可能
        promise
        p
        reason
        pPromiseResult の値
        対象
        設定群オブジェクト大域オブジェクト
      3. [16] 結果を、イベント取消なら 「取り扱われた (handled) 」、 なら「取り扱われなかった (not handled) 」 に設定します。
        エラーの報告も参照。
      4. [19] 結果が「取り扱われなかった」の場合、
        1. [23] 拒絶について開発者コンソールに報告して構いません。
      5. [17] pPromiseIsHandledなら、
        1. [18] 設定群オブジェクト未決拒絶された約束弱集合p を追加します。

[48] この処理は、マイクロタスクチェックポイントを行う処理から呼び出されます。

歴史

[43] IRC logs: freenode / #whatwg / 20140912 ( ( 版)) http://krijnhoetmer.nl/irc-logs/whatwg/20140912#l-688

[44] [whatwg] An API for unhandled promise rejections ( (Domenic Denicola 著, 版)) http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Sep/0024.html

[57] domenic/unhandled-rejections-browser-spec ( 版) https://github.com/domenic/unhandled-rejections-browser-spec

[58] 1179244 – Dispatch events for promises with unhandled rejections ( 版) https://bugzilla.mozilla.org/show_bug.cgi?id=1179244

[61] Bug 150358 – Support for promise rejection events ( 版) https://bugs.webkit.org/show_bug.cgi?id=150358

[1] Add promise rejection tracking events · whatwg/html@61ccc05 ( 版) https://github.com/whatwg/html/commit/61ccc05b7437ba947390928f9e526da49550fed0

[40] Rewrite script execution on top of ES · whatwg/html@4891d18 ( 版) https://github.com/whatwg/html/commit/4891d18aaf2df1d40aa61f467a5a10cfc19dd85d

[41] Restore definition of "Reject" lost in 079cbb861a99e9e857a3f2a169c0be… · heycam/webidl@326291e ( 版) https://github.com/heycam/webidl/commit/326291e58cf0b6e3677edb8c62682e41acaf7faf

[45] Sync with recent changes to the JS spec's job queue · whatwg/html@5af258f ( 版) https://github.com/whatwg/html/commit/5af258f33e3e2f55eb30e611cb7aee625a8bd16a

[46] Clarify settings object, realm, and global relationships · whatwg/html@0866f1b ( 版) https://github.com/whatwg/html/commit/0866f1b3f4b4ea5a99a30909e9bbe557dea0b460

[65] Fix writable stream writer manual usage example (domenic著, ) https://github.com/whatwg/streams/commit/3dffaaa475840161ee05d1d1e0c931046361239d

[66] Use the DOM manipulation task source for promise-related events (CYBAI著, ) https://github.com/whatwg/html/commit/d0feee54f85f60617811f2ea32a115e34233e606

[67] "Notify about rejected promises" is missing a task source · Issue #3731 · whatwg/html () https://github.com/whatwg/html/issues/3731

[68] Use DOM manipulation task source for promise related events by CYBAI · Pull Request #4462 · whatwg/html () https://github.com/whatwg/html/pull/4462

[69] Add reference to DOM manipulation task source for unhandled promise r… by KiChjang · Pull Request #3844 · whatwg/html () https://github.com/whatwg/html/pull/3844