From 90afa576ae0d1a7cfbca098e5a476f1fcffca663 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Sat, 4 Sep 2021 00:26:08 +0900 Subject: Global_Objects/Promise を更新 (#2227) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Markdownに変換 - 2021/08/03 時点の英語版に同期 --- .../reference/global_objects/promise/index.html | 365 ----------------- .../reference/global_objects/promise/index.md | 435 +++++++++++++++++++++ 2 files changed, 435 insertions(+), 365 deletions(-) delete mode 100644 files/ja/web/javascript/reference/global_objects/promise/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/index.md (limited to 'files') diff --git a/files/ja/web/javascript/reference/global_objects/promise/index.html b/files/ja/web/javascript/reference/global_objects/promise/index.html deleted file mode 100644 index 3b1d149baa..0000000000 --- a/files/ja/web/javascript/reference/global_objects/promise/index.html +++ /dev/null @@ -1,365 +0,0 @@ ---- -title: Promise -slug: Web/JavaScript/Reference/Global_Objects/Promise -tags: - - Class - - ECMAScript 2015 - - JavaScript - - Promise - - Reference - - クラス - - プロミス -translation_of: Web/JavaScript/Reference/Global_Objects/Promise ---- -
{{JSRef}}
- -

Promise オブジェクトは非同期処理の最終的な完了処理 (もしくは失敗) およびその結果の値を表現します。

- -

プロミスの挙動と使用法について学ぶには、最初に Promise の使用をお読みください。

- -

解説

- -

Promise インターフェイスは作成時点では分からなくてもよい値へのプロキシです。 Promise を用いることで、非同期アクションの成功や失敗に対するハンドラーを関連付けることができます。これにより、非同期メソッドは、最終的な値を返すのではなく、未来のある時点で値を持つ Promise を返すことで、同期メソッドと同じように値を返すことができるようになります。

- -

Promise の状態は以下のいずれかとなります。

- - - -

待機状態のプロミスは、何らかの値を持つ満足 (fulfilled) 状態、もしくは何らかの理由 (エラー) を持つ拒絶 (rejected) 状態のいずれかに変わります。そのどちらとなっても、then メソッドによって関連付けられたハンドラーが呼び出されます。 (対応するハンドラーが割り当てられたとき、既にプロミスが成功または失敗していても、そのハンドラーは呼ばれます。よって、非同期処理とその関連付けられたハンドラーとの競合は発生しません。)

- -

{{JSxRef("Promise.then", "Promise.prototype.then()")}} メソッドと {{JSxRef("Promise.catch", "Promise.prototype.catch()")}} メソッドもまた Promise を返すので、これらをチェーン (連鎖) させることができます。

- -

- -
-

混乱を避けるために: Scheme に代表されるいくつかの言語では、遅延評価や計算を延期する機構を持っており、これらも "Promise" と呼ばれます。 JavaScript における Promise は、すでに起きつつある処理を表します。そしてこの処理はコールバックを使うことでチェーンさせることができます。式を遅延評価する方法を探しているのであれば、引数なしのアロー関数を考えてください。 f = () => expression のように実現でき、遅延評価される式が作成され、 f() を呼ぶことでその式を評価できます。

-
- -
-

: Promise は fulfilled か failed のどちらかになった場合は、 pending ではなく settled と呼ばれます。また解決 (resolved) という用語も目にされたことがあると思います。解決とは、Promise が解決または他の promise の状態にマッチするために" locked in "したことを意味します。States and fates では、 Promise の技術についてより詳細に述べられています。

-
- -

連鎖したプロミス

- -

promise.then(), promise.catch(), promise.finally() の各メソッドは、決定したプロミスにさらなるアクションを関連付けるために使用されます。これらのメソッドはまた、新しく生成されたプロミスオブジェクトを返します。例えば、このようになります。

- -
-
-
const myPromise =
-  (new Promise(myExecutorFunc))
-  .then(handleFulfilledA,handleRejectedA)
-  .then(handleFulfilledB,handleRejectedB)
-  .then(handleFulfilledC,handleRejectedC);
-
-// または、おそらく次の方がよい ...
-
-const myPromise =
-  (new Promise(myExecutorFunc))
-  .then(handleFulfilledA)
-  .then(handleFulfilledB)
-  .then(handleFulfilledC)
-  .catch(handleRejectedAny);
-
-
- -

拒絶されたプロミスの処理が早すぎると、プロミスの連鎖のさらに下の方に影響を及ぼします。エラーはすぐに処理しなければならないので、選択の余地がないこともあります。 (結果を処理するためのテクニックについては、下記の例の throw -999 を参照してください。) 一方で、すぐに必要がない場合は、最後の .catch() 文までエラー処理をしない方がシンプルです。

- -

これら2つの関数のシグネチャはシンプルで、任意の型の引数を1つだけ受け取ることができます。これらの関数を書くのはプログラマーです。これらの関数の終了条件は、チェーン内の次のプロミスの「解決」状態を決定します。 throw 以外の終了条件は "解決" の状態を生み出し、一方、 throw で終了すると "拒否" の状態を生み出します。

- -
handleFulfilled(value)       { /*...*/; return nextValue;  }
-handleRejection(reason)  { /*...*/; throw  nextReason; }
-handleRejection(reason)  { /*...*/; return nextValue;  }
- -

返される nextValue は、別のプロミスオブジェクトにすることもでき、この場合はプロミスは動的にチェーンに挿入されます。

- -

.then() が適切な関数欠いている場合、処理は単純にチェーンの次のリンクへと続きます。したがってチェーンは、すべての handleRejection を最後の .catch() まで、安全に省略することができます。 同様に、.catch() は、実際には handleFulfilled 用のスロットのないただの .then() です。

- -

プロミスのチェーンはロシアの人形のように入れ子にすることができますが、スタックの最上位のように取り出します。チェーンの最初のプロミスは最も深いところに入れ子になり、最初に取り出されます。

- -
(promise D, (promise C, (promise B, (promise A) ) ) )
- -

nextValue がプロミスである場合、その効果は動的な置換です。 return によってプロミスが取り出されますが、 nextValue のプロミスはその場所に押し込まれます。上に示した入れ子では、"promise B" に関連付けられた .then() が "promise X" の nextValue を返すとします。 結果としての入れ子は以下のようになります。

- -
(promise D, (promise C, (promise X) ) )
- -

プロミスは複数の入れ子に参加することができます。以下のコードでは、 promiseA が「確定」状態に移行すると、 .then() の両方のインスタンスが呼び出されます。

- -
const promiseA = new Promise(myExecutorFunc);
-const promiseB = promiseA.then(handleFulfilled1, handleRejected1);
-const promiseC = promiseA.then(handleFulfilled2, handleRejected2);
-
- -

既に「解決済み」のプロミスにアクションを割り当てることができます。その場合、アクションは (適切であれば) 最初の非同期の機会に実行されます。プロミスは非同期であることが保証されていることに注意してください。したがって、既に「解決済み」のプロミスに対するアクションは、スタックがクリアされ、クロックティックが経過した後にのみ実行されます。この効果は setTimeout(action,10) とよく似ています

- -
const promiseA = new Promise( (resolutionFunc,rejectionFunc) => {
-    resolutionFunc(777);
-});
-// この時点で、 "promiseA" はすでに解決されています。
-promiseA.then( (val) => console.log("asynchronous logging has val:",val) );
-console.log("immediate logging");
-
-// 以下の順序で出力が行われます。
-// immediate logging
-// asynchronous logging has val: 777
-
- -

コンストラクター

- -
-
{{jsxref("Promise/Promise", "Promise()")}}
-
新しい Promise オブジェクトを生成します。このコンストラクターは主にまだプロミスに対応していない関数をラップするために使われます。
-
- -

静的メソッド

- -
-
{{JSxRef("Promise.all", "Promise.all(iterable)")}}
-
すべてのプロミスが解決されるか、拒否されるかするまで待ちます。
-
返却されたプロミスが解決された場合、解決されたプロミスが、複数のプロミスが含まれる iterable で定義された通りの順番で入った集合配列の値によって解決されます。
-
拒否された場合は、 iterable の中で拒否された最初のプロミスの理由によって拒否されます。
-
{{JSxRef("Promise.allSettled", "Promise.allSettled(iterable)")}}
-
すべての Promise が完了する (それぞれが解決するか、拒否される) まで待ちます。
-
Promise を返し、これはすべての与えられた Promise が解決または拒否された後で、それぞれの Promise の結果を記述するオブジェクトの配列で解決されます。
-
{{JSxRef("Promise.any", "Promise.any(iterable)")}}
-
Promise オブジェクトの反復可能オブジェクトを取り、反復可能オブジェクトの中のプロミスのうちの一つが満足され次第、そのプロミスから受け取った値で解決する単一のプロミスを返します。
-
{{JSxRef("Promise.race", "Promise.race(iterable)")}}
-
Promise のうちの1つが解決または拒否されるまで待ちます。
-
返された Promise が解決された場合、 iterable の中で最初に解決された Promise の値によって解決されます。
-
拒否された場合、最初に拒否された Promise の理由によって拒否されます。
-
{{JSxRef("Promise.reject", "Promise.reject(reason)")}}
-
与えられた理由で拒否された新しい Promise オブジェクトを返します。
-
{{JSxRef("Promise.resolve", "Promise.resolve(value)")}}
-
与えられた値で解決された新しい Promise オブジェクトを返します。もし値が thenable (つまり then メソッドを持っているオブジェクト) ならば、返される Promise はその thenable をたどり、その結果を採用します。そうでなければ、返される Promise は与えられた値で解決されます。
-
一般に、ある値がプロミスかどうかがわからない場合は、{{JSxRef("Promise.resolve", "Promise.resolve(value)")}} を使って Promise にして扱います。
-
- -

インスタンスメソッド

- -
-
{{jsxref("Promise.prototype.catch()")}}
-
プロミスに失敗ハンドラーコールバックを付加します。呼ばれるとコールバックの返値、または、オリジナルのプロミスが成功しているなら、その成功値によって完了している新しいプロミスを返します。
-
{{jsxref("Promise.prototype.then()")}}
-
プロミスに成功ハンドラーと失敗ハンドラーを付加します。呼ばれたハンドラーの戻り値によって解決している新しいプロミスを返します。または、プロミスが扱われなかった場合 (つまり onFulfilledonRejected が関数でない場合) には、元の完了した値に解決しているプロミスを返します。
-
{{jsxref("Promise.prototype.finally()")}}
-
プロミスにハンドラーを付加し、元のプロミスが解決されたときに解決される新しいプロミスを返します。このハンドラーは、成功か失敗かに関わらず、元のプロミスが完了したときに呼ばれます。
-
- -

- -

基本的な使用例

- -
let myFirstPromise = new Promise((resolve, reject) => {
-  // We call resolve(...) when what we were doing asynchronously was successful, and reject(...) when it failed.
-  // In this example, we use setTimeout(...) to simulate async code.
-  // In reality, you will probably be using something like XHR or an HTML5 API.
-  setTimeout( function() {
-    resolve("Success!")  // Yay! Everything went well!
-  }, 250)
-})
-
-myFirstPromise.then((successMessage) => {
-  // successMessage is whatever we passed in the resolve(...) function above.
-  // It doesn't have to be a string, but if it is only a succeed message, it probably will be.
-  console.log("Yay! " + successMessage)
-});
-
-
- -

多様な状況に対応した例

- -

この例では、プロミス機能を使用するための多様なテクニックと、発生する可能性のある多様な状況を示しています。これを理解するには、まずコードブロックの一番下までスクロールして、プロミスの連鎖を調べてください。最初のプロミスが提供されると、プロミスの連鎖が続きます。このチェーンは .then() の呼び出しで構成され、通常は (必ずしもそうとは限りませんが) 最後に単一の .catch() があり、オプションで .finally() が続きます。この例では、プロミスチェーンはカスタムで書かれた new Promise() コンストラクターによって開始されますが、実際には、プロミスチェーンは通常、プロミスを返す API 関数 (他の誰かが書いたもの) から開始されます。

- -

関数 tetheredGetNumber() の例では、非同期呼び出しを設定している間、またはコールバック内で、またはその両方で reject() を使用してプロミスを生成することを示しています。 関数 promiseGetWord() は、API 関数がどのように自己完結型の方法でプロミスを生成して返すかを示しています。

- -

関数 troubleWithGetNumber()throw() で終わることに注意してください。これは、 ES6 のプロミスチェーンでは、エラーが発生した後で、 "throw()" がなく、エラーが "fixed" であるようにみえても、すべての .then() のプロミスを通過するため、強制的に行われています。これは面倒なので、 .then() プロミスのチェーン全体で rejectionFunc を省略して、最終的な catch() で単一の rejectionFunc を使用するのが一般的です。 別の方法としては、特別な値を投げるという方法があります (この場合は"-999" ですが、カスタムのエラー種別の方が適切です)。

- -

このコードは NodeJS で実行できます。実際にエラーが発生しているのを見ることで理解度が高まります。より多くのエラーを強制的に発生させるには、 threshold の値を変更します。

- -
"use strict";
-
-// To experiment with error handling, "threshold" values cause errors randomly
-const THRESHOLD_A = 8; // can use zero 0 to guarantee error
-
-function tetheredGetNumber(resolve, reject) {
-  try {
-    setTimeout(
-      function() {
-        const randomInt = Date.now();
-        const value = randomInt % 10;
-        try {
-          if(value >= THRESHOLD_A) {
-            throw new Error(`Too large: ${value}`);
-          }
-        } catch(msg) {
-            reject(`Error in callback ${msg}`);
-        }
-      resolve(value);
-      return;
-    }, 500);
-    // To experiment with error at set-up, uncomment the following 'throw'.
-    // throw new Error("Bad setup");
-  } catch(err) {
-    reject(`Error during setup: ${err}`);
-  }
-  return;
-}
-
-function determineParity(value) {
-  const isOdd = value % 2 ? true : false ;
-  const parityInfo = { theNumber: value, isOdd: isOdd };
-  return parityInfo;
-}
-
-function troubleWithGetNumber(reason) {
-  console.error(`Trouble getting number: ${reason}`);
-  throw -999; // must "throw" something, to maintain error state down the chain
-}
-
-function promiseGetWord(parityInfo) {
-  // The "tetheredGetWord()" function gets "parityInfo" as closure variable.
-  var tetheredGetWord = function(resolve,reject) {
-    const theNumber = parityInfo.theNumber;
-    const threshold_B = THRESHOLD_A - 1;
-    if(theNumber >= threshold_B) {
-      reject(`Still too large: ${theNumber}`);
-    } else {
-      parityInfo.wordEvenOdd = parityInfo.isOdd ? 'odd' : 'even';
-      resolve(parityInfo);
-    }
-    return;
-  }
-  return new Promise(tetheredGetWord);
-}
-
-(new Promise(tetheredGetNumber))
-  .then(determineParity,troubleWithGetNumber)
-  .then(promiseGetWord)
-  .then((info) => {
-    console.log("Got: ",info.theNumber," , ", info.wordEvenOdd);
-    return info;
-  })
-  .catch((reason) => {
-    if(reason === -999) {
-      console.error("Had previously handled error");
-    }
-    else {
-      console.error(`Trouble with promiseGetWord(): ${reason}`);
-    }
-   })
-  .finally((info) => console.log("All done"));
-
-
- -

応用例

- - - -

以下の例は Promise の仕組みを示したものです。 testPromise() メソッドは {{HTMLElement("button")}} をクリックする度に呼び出されます。testPromise() メソッドは、 {{domxref("window.setTimeout()")}} を用いて、1秒から 3秒のランダムな時間の後、メソッドがこれまでに呼ばれた回数で成功する Promise を作成します。 Promise() コンストラクターは Promise を作成するために使用されます。

- -

プロミスが満足したことは、 {{JSxRef("Promise.prototype.then()","p1.then()")}} で設定されたコールバックによって記録されます。この記録から、メソッドの同期処理部分が、 Promise による非同期処理からどのように分離されているかがわかります。

- -
'use strict';
-var promiseCount = 0;
-
-function testPromise() {
-    let thisPromiseCount = ++promiseCount;
-
-    let log = document.getElementById('log');
-    log.insertAdjacentHTML('beforeend', thisPromiseCount +
-        ') 開始 (<small>同期処理開始</small>)<br/>');
-
-    // 新しい Promise を作成: 1~3秒後に結果を返すことを約束します
-    let p1 = new Promise(
-        // executor 関数は Promise の成功または失敗に応じて呼ばれます
-        //
-       (resolve, reject) => {
-            log.insertAdjacentHTML('beforeend', thisPromiseCount +
-                ') Promise 開始 (<small>非同期処理開始</small>)<br/>');
-            // 非同期を作成するための一例です
-            window.setTimeout(
-                function() {
-                    // 約束を果たしました!
-                    resolve(thisPromiseCount);
-                }, Math.random() * 2000 + 1000);
-        }
-    );
-
-    // Promise が成功した時に何をするかを定めます then() で成功した時
-    // catch() で失敗した時
-    p1.then(
-        // メッセージと値を記録します
-        function(val) {
-            log.insertAdjacentHTML('beforeend', val +
-                ') Promise 成功 (<small>非同期処理終了</small>)<br/>');
-        }).catch(
-        // 失敗した理由を記録します
-       (reason) => {
-            console.log('Handle rejected promise ('+reason+') here.');
-        });
-
-    log.insertAdjacentHTML('beforeend', thisPromiseCount +
-        ') Promise は作成されました (<small>同期処理終了</small>)<br/>');
-}
- - - -

この例はボタンをクリックすると実行されます。 (ブラウザーが Promise に対応している必要があります。)

- -

短い時間の間に何度かボタンをクリックすると、それぞれの promise が次々と成功するのがわかります。

- -

{{EmbedLiveSample("Advanced_Example", "500", "200")}}

- -

XHR による画像の読み込み

- -

Promise と {{domxref("XMLHttpRequest")}} で画像を読み込む別の例は、 MDN GitHub js-examples リポジトリにあり、動作を確認することができます。それぞれの行のコメントで Promise と XHR の構造がよくわかるはずです。

- -

仕様書

- - - - - - - - - - -
仕様書
{{SpecName('ESDraft', '#sec-promise-objects', 'Promise')}}
- -

ブラウザーの互換性

- -

{{Compat("javascript.builtins.Promise")}}

- -

関連情報

- - diff --git a/files/ja/web/javascript/reference/global_objects/promise/index.md b/files/ja/web/javascript/reference/global_objects/promise/index.md new file mode 100644 index 0000000000..821495840f --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/index.md @@ -0,0 +1,435 @@ +--- +title: Promise +slug: Web/JavaScript/Reference/Global_Objects/Promise +tags: + - クラス + - ECMAScript 2015 + - JavaScript + - Promise + - Reference + - promise.all + - Polyfill +browser-compat: javascript.builtins.Promise +translation_of: Web/JavaScript/Reference/Global_Objects/Promise +--- +{{JSRef}} + +**`Promise`** オブジェクトは、非同期処理の完了 (もしくは失敗) の結果およびその結果の値を表します。 + +{{AvailableInWorkers}} + +プロミスの挙動と使用法について学ぶには、最初に[プロミスの使用](/ja/docs/Web/JavaScript/Guide/Using_promises)をお読みください。 + +## 解説 + +プロミス (**`Promise`**) は、作成された時点では分からなくてもよい値へのプロキシーです。非同期のアクションの成功値または失敗理由にハンドラーを結びつけることができます。これにより、非同期メソッドは結果の値を返す代わりに、未来のある時点で値を提供する*プロミス*を返すことで、同期メソッドと同じように値を返すことができるようになります。 + +`Promise` の状態は以下のいずれかとなります。 + +- 待機 (_pending_): 初期状態。成功も失敗もしていません。 +- 履行 (_fulfilled_): 処理が成功して完了したことを意味します。 +- 拒否 (_rejected_): 処理が失敗したことを意味します。 + +待機状態のプロミスは、何らかの値を持つ履行 (_fulfilled_) 状態、もしくは何らかの理由 (エラー) を持つ拒否 (_rejected_) 状態のいずれかに変わります。そのどちらとなっても、`then` メソッドによって関連付けられたハンドラーが呼び出されます。対応するハンドラーが割り当てられたとき、既にプロミスが履行または拒否状態になっていても、そのハンドラーは呼び出されます。よって、非同期処理とその関連付けられたハンドラーとの競合は発生しません。 + +`{{JSxRef("Promise.then", "Promise.prototype.then()")}}` メソッドと `{{JSxRef("Promise.catch", "Promise.prototype.catch()")}}` メソッドもまたプロミスを返すので、これらを連鎖 (chain) させることができます。 + +![](promises.png) + +> **Note:** Scheme に代表される一部の言語では、遅延評価や計算を延期する機構を持っており、これらも「プロミス」と呼ばれます。 JavaScript におけるプロミスは、すでに起きつつある処理を表し、この処理はコールバックを使うことで連鎖させることができます。式を遅延評価する方法を探しているのであれば、引数なしのアロー関数を検討してください。 `f = () => expression` で遅延評価される式が作成でき、 `f()` を実行することで評価を実行することができます。 + +> **Note:** プロミスは履行状態または拒否状態になった場合は、待機ではなく決定 (_settled_) と呼ばれます。また解決 (_resolved_) という用語も見かけるでしょう。これはプロミスが決定したか、他のプロミスの状態に一致させるために「ロックイン」したことを表します。 [States and fates](https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md) には、プロミスの用語についての詳細説明があります。 + +### 複数のプロミスの連鎖 + +`promise.then()`, `promise.catch()`, `promise.finally()` の各メソッドは、決定したプロミスにさらなるアクションを結びつけるために使用します。 + +`.then()` メソッドは、最大で 2 つの引数を取ります。1 番目の引数は、プロミスが解決した場合のコールバック関数で、 2 番目の引数は、拒否された場合のコールバック関数です。それぞれの `.then()` は新たに生成されたプロミスオブジェクトを返します。このオブジェクトは、オプションで連鎖に使用することができます。例えば、このようになります。 + +```js +const myPromise = new Promise((resolve, reject) => { + setTimeout(() => { + resolve('foo'); + }, 300); +}); + +myPromise + .then(handleResolvedA, handleRejectedA) + .then(handleResolvedB, handleRejectedB) + .then(handleResolvedC, handleRejectedC); +``` + +`.then()` に Promise オブジェクトを返すコールバック関数がない場合でも、連鎖の次のリンクへと処理が進みます。したがって、連鎖では最後の `.catch()` まで、すべての*拒否*のコールバック関数を省略しても安全です。 + +それぞれの `.then()` で拒否されたプロミスを扱うと、プロミスの連鎖のさらに先に影響を及ぼします。エラーを直ちに処理しなければならないため、選択の余地がない場合もあります。このような場合には、連鎖的にエラー状態を維持するために、何らかの種類のエラーを発生させる必要があります。一方で、緊急の必要性がない場合は、最後の `.catch()` ステートメントまでエラー処理を行わない方がシンプルです。 `.catch()` は、実際には、単なる `.then()` からプロミスが解決されたときのためのコールバック関数のスロットを抜いたものです。 + +```js +myPromise +.then(handleResolvedA) +.then(handleResolvedB) +.then(handleResolvedC) +.catch(handleRejectedAny); +``` + +{{JSxRef("Functions/Arrow_functions", "アロー関数式", "", 1)}}をコールバック関数に使用すると、プロミス連鎖の実装は次のようになるでしょう。 + +```js +promise1 +.then(value => { return value + ' and bar'; }) +.then(value => { return value + ' and bar again'; }) +.then(value => { return value + ' and again'; }) +.then(value => { return value + ' and again'; }) +.then(value => { console.log(value) }) +.catch(err => { console.log(err) }); +``` + +プロミスの終了条件は、その連鎖内の次のプロミスの「決定」状態を決定します。解決」状態はプロミスの完了が成功したことを示し、「拒否」状態は成功しなかったことを示します。連鎖内で解決されたそれぞれのプロミスの返値は、次の `.then()` に渡され、拒否された理由は連鎖内の次の拒否ハンドラー関数に渡されます。 + +連鎖のプロミスは、ロシア人形のように入れ子になっていますが、スタックの一番上のように取り出されます。連鎖の最初のプロミスは最も深くネストされており、最初に取り出されます。 + +```plain +(promise D, (promise C, (promise B, (promise A) ) ) ) +``` + +`nextValue` がプロミスである場合、その効果は動的な置換です。 `return` によってプロミスが取り出されますが、 `nextValue` のプロミスはその場所に押し込まれます。上に示した入れ子では、"promise B" に関連付けられた `.then()` が "promise X" の `nextValue` を返すとします。 結果としての入れ子は以下のようになります。 + +```plain +(promise D, (promise C, (promise X) ) ) +``` + +プロミスは複数の入れ子に参加することができます。以下のコードでは、 `promiseA` が「決定」状態に移行すると、 `.then()` の両方のインスタンスが呼び出されます。 + +```js +const promiseA = new Promise(myExecutorFunc); +const promiseB = promiseA.then(handleFulfilled1, handleRejected1); +const promiseC = promiseA.then(handleFulfilled2, handleRejected2); +``` + +既に「決定」状態のプロミスにアクションを割り当てることができます。その場合、アクションは (適切であれば) 最初の非同期の機会に実行されます。プロミスは非同期であることが保証されていることに注意してください。したがって、既に「解決」状態のプロミスに対するアクションは、スタックがクリアされ、クロックティックが経過した後にのみ実行されます。この効果は `setTimeout(action,10)` とよく似ています + +```js +const promiseA = new Promise( (resolutionFunc,rejectionFunc) => { + resolutionFunc(777); +}); +// この時点で、 "promiseA" はすでに解決されています。 +promiseA.then( (val) => console.log("asynchronous logging has val:",val) ); +console.log("immediate logging"); + +// 以下の順序で出力が行われます。 +// immediate logging +// asynchronous logging has val: 777 +``` + +### 現行の設定オブジェクトの追跡 + +設定オブジェクト (settings object) とは、 JavaScript コードの実行時に追加情報を提供する[環境](https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object)のことです。これには、領域やモジュールマップのほか、オリジンなどの HTML 固有の情報も含まれます。現行の設定オブジェクトが追跡されるのは、特定のユーザーコードに対してどの設定オブジェクトを使用すべきかをブラウザーが確実に把握するためです。 + +これをより良く理解するために、領域がどのように問題になるかを詳しく見てみましょう。領域 (**realm**) とは、大まかに言うとグローバルオブジェクトのことです。領域の特徴は、JavaScript のコードを実行するために必要な情報をすべて保持していることです。これには [`Array`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Array) や [`Error`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Error) などのオブジェクトが含まれます。それぞれの設定オブジェクトはこれらの「コピー」を持っており、共有されていません。そのため、プロミスとの関係で予期しない動作をすることがあります。これを回避するために、**現行の設定オブジェクト** (incumbent settings object) と呼ばれるものを追跡します。これは、ある関数呼び出しを担当するユーザーコードのコンテキストに固有の情報を表します。 + +これをもう少し詳しく説明するために、文書に埋め込まれた [` + +``` + +同じ概念をプロミスに適用します。上の例を少し変えてみると、こうなります。 + +```html + + + +``` + +これを変更して、文書内の ` + +``` + +```html + + + +``` + +上記の例では、現行の設定オブジェクトが追跡されたときのみ `