From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../global_objects/promise/all/index.html | 236 +++++++++++++ .../global_objects/promise/allsettled/index.html | 100 ++++++ .../global_objects/promise/any/index.html | 154 +++++++++ .../global_objects/promise/catch/index.html | 190 +++++++++++ .../global_objects/promise/finally/index.html | 109 ++++++ .../reference/global_objects/promise/index.html | 367 +++++++++++++++++++++ .../global_objects/promise/promise/index.html | 109 ++++++ .../global_objects/promise/race/index.html | 182 ++++++++++ .../global_objects/promise/reject/index.html | 74 +++++ .../global_objects/promise/resolve/index.html | 139 ++++++++ .../global_objects/promise/then/index.html | 300 +++++++++++++++++ 11 files changed, 1960 insertions(+) create mode 100644 files/ja/web/javascript/reference/global_objects/promise/all/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/allsettled/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/any/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/catch/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/finally/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/promise/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/race/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/reject/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/resolve/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/promise/then/index.html (limited to 'files/ja/web/javascript/reference/global_objects/promise') diff --git a/files/ja/web/javascript/reference/global_objects/promise/all/index.html b/files/ja/web/javascript/reference/global_objects/promise/all/index.html new file mode 100644 index 0000000000..8a3c00e020 --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/all/index.html @@ -0,0 +1,236 @@ +--- +title: Promise.all() +slug: Web/JavaScript/Reference/Global_Objects/Promise/all +tags: + - ECMAScript 2015 + - JavaScript + - Method + - Promise + - all + - メソッド +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/all +--- +
{{JSRef}}
+ +

Promise.all(iterable) メソッドは単一の {{jsxref("Promise")}} を返し、これは引数 iterable の中のすべての Promise が解決されるか、引数 iterable の中に Promise がない場合に解決されます。最初に拒否された Promise の拒否理由をもって拒否されます。

+ +
{{EmbedInteractiveExample("pages/js/promise-all.html")}}
+ + + +

構文

+ +
Promise.all(iterable);
+ +

引数

+ +
+
iterable
+
{{jsxref("Array")}} や {{jsxref("String")}} のような反復処理可能 (iterable) なオブジェクト。
+
+ +

返値

+ + + +

解説

+ +

このメソッドは複数の Promise の結果を集約するのに便利です。

+ +

完成:
+ 空の iterable が渡された場合、このメソッドはすでに解決した Promise を (同期的に) 返します。
+ 渡された Promise のすべてが満たされるか、 Promise が渡されていない場合、 Promise.all によって返される Promise が非同期的に完成されます。
+ すべての場合で、返された Promise は、引数として渡された iterableすべての値 (Promise ではない値も) を含んだ配列で完成されます。

+ +

拒否:
+ 渡された Promise のいずれかが拒否されたら、 Promise.all は非同期的に、その他の Promise が完了しているかどうかに関係なく、その拒否した Promise の値で拒否されます。

+ +

+ +

Promise.all の使用

+ +

Promise.allはすべての完成 (または最初の拒否) を待ちます。

+ +
var p1 = Promise.resolve(3);
+var p2 = 1337;
+var p3 = new Promise((resolve, reject) => {
+  setTimeout(() => {
+    resolve("foo");
+  }, 100);
+});
+
+Promise.all([p1, p2, p3]).then(values => {
+  console.log(values); // [3, 1337, "foo"]
+});
+ +

iterable に Promise ではない値が含まれる場合は無視されますが、 (Promise が成功する場合) 返される Promise 配列の値にはカウントされます。

+ +
// this will be counted as if the iterable passed is empty, so it gets fulfilled
+var p = Promise.all([1,2,3]);
+// this will be counted as if the iterable passed contains only the resolved promise with value "444", so it gets fulfilled
+var p2 = Promise.all([1,2,3, Promise.resolve(444)]);
+// this will be counted as if the iterable passed contains only the rejected promise with value "555", so it gets rejected
+var p3 = Promise.all([1,2,3, Promise.reject(555)]);
+
+// using setTimeout we can execute code after the stack is empty
+setTimeout(function() {
+    console.log(p);
+    console.log(p2);
+    console.log(p3);
+});
+
+// logs
+// Promise { <state>: "fulfilled", <value>: Array[3] }
+// Promise { <state>: "fulfilled", <value>: Array[4] }
+// Promise { <state>: "rejected", <reason>: 555 }
+ +

Promise.all の非同期性・同期性

+ +

以下の例では Promise.all の非同期性 (または渡されたiterable が空の場合、同期性) を実演します。

+ +
// we are passing as argument an array of promises that are already resolved,
+// to trigger Promise.all as soon as possible
+var resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];
+
+var p = Promise.all(resolvedPromisesArray);
+// immediately logging the value of p
+console.log(p);
+
+// using setTimeout we can execute code after the stack is empty
+setTimeout(function() {
+    console.log('the stack is now empty');
+    console.log(p);
+});
+
+// logs, in order:
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "fulfilled", <value>: Array[2] }
+
+ +

Promise.all が拒否されたときも同じことが起きます.。

+ +
var mixedPromisesArray = [Promise.resolve(33), Promise.reject(44)];
+var p = Promise.all(mixedPromisesArray);
+console.log(p);
+setTimeout(function() {
+    console.log('the stack is now empty');
+    console.log(p);
+});
+
+// logs
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "rejected", <reason>: 44 }
+
+ +

しかし、Promise.all は渡された iterable が空の場合だけ同期的に解決します。

+ +
var p = Promise.all([]); // will be immediately resolved
+var p2 = Promise.all([1337, "hi"]); // non-promise values will be ignored, but the evaluation will be done asynchronously
+console.log(p);
+console.log(p2)
+setTimeout(function() {
+    console.log('the stack is now empty');
+    console.log(p2);
+});
+
+// logs
+// Promise { <state>: "fulfilled", <value>: Array[0] }
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "fulfilled", <value>: Array[2] }
+
+ +

Promise.allのフェイルファストの挙動

+ +

Promise.all は要素のひとつでも拒否されると拒否します。例えば、タイムアウト後に4つの Promise が解決しても、1つの Promise が直ちに拒否された場合、 Promise.all は直ちに拒否します。

+ +
var p1 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('one'), 1000);
+});
+var p2 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('two'), 2000);
+});
+var p3 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('three'), 3000);
+});
+var p4 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('four'), 4000);
+});
+var p5 = new Promise((resolve, reject) => {
+  reject(new Error('reject'));
+});
+
+
+// Using .catch:
+Promise.all([p1, p2, p3, p4, p5])
+.then(values => {
+  console.log(values);
+})
+.catch(error => {
+  console.log(error.message)
+});
+
+//From console:
+//"reject"
+
+
+ +

この動作は失敗する可能性を制御することで変更することができます。

+ +
var p1 = new Promise((resolve, reject) => {
+  setTimeout(() => resolve('p1_delayed_resolvement'), 1000);
+});
+
+var p2 = new Promise((resolve, reject) => {
+  reject(new Error('p2_immediate_rejection'));
+});
+
+Promise.all([
+  p1.catch(error => { return error }),
+  p2.catch(error => { return error }),
+]).then(values => {
+  console.log(values[0]) // "p1_delayed_resolvement"
+  console.log(values[1]) // "Error: p2_immediate_rejection"
+})
+
+ +

仕様書

+ + + + + + + + + + + + + + + + + + + +
仕様書状態備考
{{SpecName('ES2015', '#sec-promise.all', 'Promise.all')}}{{Spec2('ES2015')}}ECMA 標準としての初回定義
{{SpecName('ESDraft', '#sec-promise.all', 'Promise.all')}}{{Spec2('ESDraft')}} 
+ +

ブラウザーの対応

+ + + +

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

+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/global_objects/promise/allsettled/index.html b/files/ja/web/javascript/reference/global_objects/promise/allsettled/index.html new file mode 100644 index 0000000000..83891f3857 --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/allsettled/index.html @@ -0,0 +1,100 @@ +--- +title: Promise.allSettled() +slug: Web/JavaScript/Reference/Global_Objects/Promise/allSettled +tags: + - JavaScript + - Method + - Promise + - Reference + - allSettled + - asynchronous + - プロミス + - メソッド + - 非同期 +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/allSettled +--- +
{{JSRef}}
+ +

Promise.allSettled() メソッドは、与えられたすべてのプロミスが満足したか拒否された後に、それぞれのプロミスの結果を記述した配列オブジェクトで解決されるプロミスを返します。

+ +

一般的には、複数の非同期タスクがあり、お互いに依存せずに正常に完了する場合や、各プロミスの結果を常に知りたい場合に使用されます。

+ +

これと比較して、 {{jsxref("Promise.all()")}} で返されるプロミスは、タスクがお互いに依存している場合や、タスクのいずれかが拒否されたときにすぐに拒否したい場合にはより適切かもしれません。

+ +
{{EmbedInteractiveExample("pages/js/promise-allsettled.html")}}
+ +

構文

+ +
Promise.allSettled(iterable);
+ +

引数

+ +
+
iterable
+
{{jsxref("Array")}} などの反復可能オブジェクトで、それぞれの要素が Promise であるものです。
+
+ +

返値

+ +

待ち状態の {{jsxref("Promise")}} で、指定されたプロミスの集合に含まれるすべてのプロミスが、正常に解決されるか拒否されるかのどちらかで完了すると、非同期に解決されます。その際、返されたプロミスのハンドラーには、元のプロミスの集合に含まれるの各プロミスの結果を含む配列が入力として渡されます。

+ +

ただし、空の反復可能オブジェクトが引数として渡された場合に限りPromise.allSettled() は空の配列として解決済みの Promise オブジェクトを返します。

+ +

出力されるそれぞれのオブジェクトには、 status の文字列が存在します。 status が fulfilled であれば、 value が存在します。 status が rejected であれば、 reason が存在します。 value (または reason) はそれぞれのプロミスがどの値で解決 (または拒否) されたかを反映します。

+ +

+ +

Promise.allSettled の使用

+ +
Promise.allSettled([
+  Promise.resolve(33),
+  new Promise(resolve => setTimeout(() => resolve(66), 0)),
+  99,
+  Promise.reject(new Error('an error'))
+])
+.then(values => console.log(values));
+
+// [
+//   {status: "fulfilled", value: 33},
+//   {status: "fulfilled", value: 66},
+//   {status: "fulfilled", value: 99},
+//   {status: "rejected",  reason: Error: an error}
+// ]
+
+ +

仕様書

+ + + + + + + + + + + + +
仕様書
{{SpecName('ESDraft', '#sec-promise.allsettled', 'Promise.allSettled')}}
+ +

ブラウザーの互換性

+ + + +

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

+ +

実装の進捗状況

+ +

以下の表は、クロスブラウザーの安定性にまだ達していないこの機能の日々の実装状況を示しています。このデータは、 JavaScript の標準テストスイートである Test262 で関連する機能テストをナイトリービルド、または各ブラウザの JavaScript エンジンの最新リリースで実行することで生成されます。

+ +
{{EmbedTest262ReportResultsTable("Promise.allSettled")}}
+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/global_objects/promise/any/index.html b/files/ja/web/javascript/reference/global_objects/promise/any/index.html new file mode 100644 index 0000000000..bc5e1c5514 --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/any/index.html @@ -0,0 +1,154 @@ +--- +title: Promise.any() +slug: Web/JavaScript/Reference/Global_Objects/Promise/any +tags: + - Experimental + - JavaScript + - Method + - NeedsCompatTable + - Promise + - Reference + - プロミス + - メソッド + - 実験的 +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/any +--- +
{{JSRef}}
+ +

Promise.any() は {{JSxRef("Promise")}} オブジェクトの反復可能オブジェクトを受け取り、反復可能オブジェクトの中にあるプロミスの一つが満足するとすぐに、そのプロミスの値で解決される単一のプロミスを返します。反復可能オブジェクトの中に満足可能なプロミスがない場合 (与えられたプロミスがすべて拒否された場合)、返されたプロミスは {{JSxRef("AggregateError")}} という、個々のエラーをグループ化した {{JSxRef("Error")}} の新しいサブクラスで拒否されます。本質的には、このメソッドは {{JSxRef("Promise.all()")}} の反対です。

+ +
+

警告! Promise.any() メソッドは実験的であり、すべてのブラウザーが対応しているわけではありません。現在は TC39 Candidate stage (Stage 4) にあります。

+
+ +

構文

+ +
Promise.any(iterable);
+ +

引数

+ +
+
iterable
+
反復可能オブジェクト、例えば {{JSxRef("Array")}} です。
+
+ +

返値

+ + + +

解説

+ +

このメソッドは、最初に満足するプロミスを返すのに便利です。1つのプロミスが満足した後に短絡するので、1つのプロミスが見つかったら他のプロミスが満足するのを待つことはありません。 {{JSxRef("Promise.all()")}} が満足した値の配列を返すのとは異なり、 (少なくとも1つのプロミスが満足したと仮定すると) 満足した値は 1 つしか得られません。これは、1つのプロミスが満足する必要があるが、どちらのプロミスが満足するかは関係ないときに有益な場合があります。また {{JSxRef("Promise.race()")}} が最初に完了した値 (満足または拒否のいずれか) を返すのとは異なり、このメソッドは最初に満足した値を返します。このメソッドは、最初のプロミスが満足するまでは、すべての拒否されたプロミスを無視します。

+ +

満足

+ +

渡されたプロミスのうちのいずれかが満足した場合、返却されるプロミスは他のプロミスが満足または拒否されているかどうかにかかわらず、満足したプロミスの値で非同期に満足します。

+ + + +

拒否

+ +

渡されたすべてのプロミスが拒否された場合、 Promise.any は {{JSxRef("AggregateError")}} オブジェクトで非同期に拒否され、これは{{JSxRef("Error")}} を継承しており、拒否された値の配列を持つ errors プロパティを含みます。

+ +

+ +

最初に満足するもの

+ +

Promise.any() は、先に拒否されたプロミスがあったとしても、最初に満足したプロミスで解決されます。これは {{jsxref("Promise.race()")}} が最初に決定したプロミスで解決または拒否されるのとは対照的です。

+ +
const pErr = new Promise((resolve, reject) => {
+  reject("Always fails");
+});
+
+const pSlow = new Promise((resolve, reject) => {
+  setTimeout(resolve, 500, "Done eventually");
+});
+
+const pFast = new Promise((resolve, reject) => {
+  setTimeout(resolve, 100, "Done quick");
+});
+
+Promise.any([pErr, pSlow, pFast]).then((value) => {
+  console.log(value);
+  // pFast fulfils first
+})
+// 期待される出力: "Done quick"
+
+ +

AggregateError での拒否

+ +

Promise.any() は満足したプロミスがないと {{jsxref("AggregateError")}} で拒否されます。

+ +
const pErr = new Promise((resolve, reject) => {
+  reject('Always fails');
+});
+
+Promise.any([pErr]).catch((err) => {
+  console.log(err);
+})
+// 期待される出力: "AggregateError: No Promise in Promise.any was resolved"
+
+ +

最初に読み込まれた画像の表示

+ +

この例では、画像を読み込んで blob を返す関数があります。 Promise.any() を使用して二つの画像を読み込み、先に利用可能になった方 (つまり、プロミスが解決された方) を表示します。

+ +
function fetchAndDecode(url) {
+  return fetch(url).then(response => {
+    if(!response.ok) {
+      throw new Error(`HTTP error! status: ${response.status}`);
+    } else {
+      return response.blob();
+    }
+  })
+}
+
+let coffee = fetchAndDecode('coffee.jpg');
+let tea = fetchAndDecode('tea.jpg');
+
+Promise.any([coffee, tea]).then(value => {
+  let objectURL = URL.createObjectURL(value);
+  let image = document.createElement('img');
+  image.src = objectURL;
+  document.body.appendChild(image);
+})
+.catch(e => {
+  console.log(e.message);
+});
+ +

仕様書

+ + + + + + + + + + + + +
仕様書
{{SpecName('Promise.any')}}
+ +

ブラウザーの互換性

+ + + +

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

+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/global_objects/promise/catch/index.html b/files/ja/web/javascript/reference/global_objects/promise/catch/index.html new file mode 100644 index 0000000000..08ef14d5a5 --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/catch/index.html @@ -0,0 +1,190 @@ +--- +title: Promise.prototype.catch() +slug: Web/JavaScript/Reference/Global_Objects/Promise/catch +tags: + - ECMAScript 2015 + - JavaScript + - Method + - Promise + - Prototype +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/catch +--- +
{{JSRef}}
+ +

catch() メソッドは Promise を返しますが、拒絶された場合のみ扱います。 {{jsxref("Promise.then", "Promise.prototype.then(undefined, onRejected)")}} の呼び出しと同じ動作をします (実際、 obj.catch(onRejected) の呼び出しは内部的に obj.then(undefined, onRejected) を呼び出しています)。つまり、返値を undefined にフォールバックしたい場合でも、 onRejected 関数を提供する必要があります。 - 例えば、 obj.catch(() => {}) のようにします。

+ +
{{EmbedInteractiveExample("pages/js/promise-catch.html")}}
+ + + +

構文

+ +
p.catch(onRejected);
+
+p.catch(function(reason) {
+   // rejection
+});
+
+ +

引数

+ +
+
onRejected
+
Promise が失敗した時に呼び出される {{jsxref("Function")}} です。この関数は一つの引数を持ちます。 +
+
reason
+
拒絶された理由です。
+
+ catch() で返される Promise は、 onRejected がエラーを発生させた場合、または返される Promise それ自体が拒絶された場合は、拒絶となります。それ以外の場合は、解決となります。
+
+ +

返値

+ +

内部的には、呼び出されたオブジェクトの Promise.prototype.then を呼び出し、引数に undefined と、受け取った onRejected ハンドラーを渡します。返値はこの呼び出しの値であり、すなわち {{jsxref("Promise")}} です。

+ +
+

なお、以下の例は Error のインスタンスを投げます。これは文字列を投げる場合と比較して、良い習慣と見なされています。そうでなければ、キャッチを実行する部分で引数が string か error かをチェックする必要があり、スタックトレースのような価値のある情報を失う可能性があります。

+
+ +

内部呼び出しの例

+ +
// overriding original Promise.prototype.then/catch just to add some logs
+(function(Promise){
+    var originalThen = Promise.prototype.then;
+    var originalCatch = Promise.prototype.catch;
+
+    Promise.prototype.then = function(){
+        console.log('> > > > > > called .then on %o with arguments: %o', this, arguments);
+        return originalThen.apply(this, arguments);
+    };
+    Promise.prototype.catch = function(){
+        console.error('> > > > > > called .catch on %o with arguments: %o', this, arguments);
+        return originalCatch.apply(this, arguments);
+    };
+
+})(this.Promise);
+
+
+
+// calling catch on an already resolved promise
+Promise.resolve().catch(function XXX(){});
+
+// logs:
+// > > > > > > called .catch on Promise{} with arguments: Arguments{1} [0: function XXX()]
+// > > > > > > called .then on Promise{} with arguments: Arguments{2} [0: undefined, 1: function XXX()]
+
+ +

解説

+ +

catch メソッドは複合したプロミスの複合のエラー処理に使用されます。これは {{jsxref("Promise")}} を返しますので、姉妹メソッドである {{jsxref("Promise.then", "then()")}} と同様の方法でチェーン可能です。

+ +

+ +

catch メソッドの使用とチェーン化

+ +
var p1 = new Promise(function(resolve, reject) {
+  resolve('Success');
+});
+
+p1.then(function(value) {
+  console.log(value); // "Success!"
+  throw new Error('oh, no!');
+}).catch(function(e) {
+  console.error(e.message); // "oh, no!"
+}).then(function(){
+  console.log('after a catch the chain is restored');
+}, function () {
+  console.log('Not fired due to the catch');
+});
+
+// 以下は、上記と同様に動作します
+p1.then(function(value) {
+  console.log(value); // "Success!"
+  return Promise.reject('oh, no!');
+}).catch(function(e) {
+  console.error(e); // "oh, no!"
+}).then(function(){
+  console.log('after a catch the chain is restored');
+}, function () {
+  console.log('Not fired due to the catch');
+});
+
+ +

エラーを投げたことを知る

+ +
// Throwing an error will call the catch method most of the time
+var p1 = new Promise(function(resolve, reject) {
+  throw new Error('Uh-oh!');
+});
+
+p1.catch(function(e) {
+  console.error(e); // "Uh-oh!"
+});
+
+// Errors thrown inside asynchronous functions will act like uncaught errors
+var p2 = new Promise(function(resolve, reject) {
+  setTimeout(function() {
+    throw new Error('Uncaught Exception!');
+  }, 1000);
+});
+
+p2.catch(function(e) {
+  console.error(e); // This is never called
+});
+
+// Errors thrown after resolve is called will be silenced
+var p3 = new Promise(function(resolve, reject) {
+  resolve();
+  throw new Error('Silenced Exception!');
+});
+
+p3.catch(function(e) {
+   console.error(e); // This is never called
+});
+ +

解決される場合

+ +
//Create a promise which would not call onReject
+var p1 = Promise.resolve("calling next");
+
+var p2 = p1.catch(function (reason) {
+    //This is never called
+    console.error("catch p1!");
+    console.error(reason);
+});
+
+p2.then(function (value) {
+    console.log("next promise's onFulfilled"); /* next promise's onFulfilled */
+    console.log(value); /* calling next */
+}, function (reason) {
+    console.log("next promise's onRejected");
+    console.log(reason);
+});
+ +

仕様書

+ + + + + + + + + + + + +
仕様書
{{SpecName('ESDraft', '#sec-promise.prototype.catch', 'Promise.prototype.catch')}}
+ +

ブラウザーの互換性

+ + + +

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

+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/global_objects/promise/finally/index.html b/files/ja/web/javascript/reference/global_objects/promise/finally/index.html new file mode 100644 index 0000000000..65fb7abeba --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/finally/index.html @@ -0,0 +1,109 @@ +--- +title: Promise.prototype.finally() +slug: Web/JavaScript/Reference/Global_Objects/Promise/finally +tags: + - JavaScript + - Method + - Promises + - Prototype + - Reference + - finally +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/finally +--- +
{{JSRef}}
+ +

finally() メソッドは {{jsxref("Promise")}} を返します。プロミスが確立したら、満足か拒否かにかかわらず、指定されたコールバック関数が実行されます。これにより、プロミスが成功裏に実行されたか否かに関わりなく、 Promise が処理された後に実行されなければならないコードを提供できます。

+ +

これによって、プロミスの {{jsxref("Promise.then", "then()")}} ハンドラーと {{jsxref("Promise.catch", "catch()")}} ハンドラーでコードが重複することを避けることができます。

+ +

構文

+ +
p.finally(onFinally);
+
+p.finally(function() {
+   // 確立 (満足または拒否)
+});
+
+ +

引数

+ +
+
onFinally
+
Promise が確立したら呼び出される {{jsxref("Function")}}。
+
+ +

返値

+ +

finally ハンドラーに指定した onFinally が設定した {{jsxref("Promise")}} を返します。

+ +

解説

+ +

プロミスが確立した後、結果に関わらず何らかの処理や後始末を行いたいなら、finally() メソッドは役立ちます。

+ +

finally() メソッドは .then(onFinally, onFinally) の呼び出しとよく似ていますが、いくつかの点が異なります。

+ + + +
+

補足: finally コールバック内で throw が行われた場合 (または、拒否されたプロミスを返した場合)、 throw を呼び出すときに指定された拒否理由と共に新しいプロミスが拒否されます。

+
+ +

+ +

finally の使用

+ +
let isLoading = true;
+
+fetch(myRequest).then(function(response) {
+    var contentType = response.headers.get("content-type");
+    if(contentType && contentType.includes("application/json")) {
+      return response.json();
+    }
+    throw new TypeError("Oops, we haven't got JSON!");
+  })
+  .then(function(json) { /* process your JSON further */ })
+  .catch(function(error) { console.error(error); /* this line can also throw, e.g. when console = {} */ })
+  .finally(function() { isLoading = false; });
+
+
+ + + +

仕様書

+ + + + + + + + + + + + +
仕様書
{{SpecName('ESDraft', '#sec-promise.prototype.finally', 'Promise.prototype.finally')}}
+ +

ブラウザーの互換性

+ + + +

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

+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/global_objects/promise/index.html b/files/ja/web/javascript/reference/global_objects/promise/index.html new file mode 100644 index 0000000000..6a41d6a21d --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/index.html @@ -0,0 +1,367 @@ +--- +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/promise/index.html b/files/ja/web/javascript/reference/global_objects/promise/promise/index.html new file mode 100644 index 0000000000..816285a046 --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/promise/index.html @@ -0,0 +1,109 @@ +--- +title: Promise() コンストラクター +slug: Web/JavaScript/Reference/Global_Objects/Promise/Promise +tags: + - Constructor + - JavaScript + - Promise + - Reference +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/Promise +--- +
{{JSRef}}
+ +

Promise コンストラクターは、主にまだプロミスに対応していない関数をラップするために使用します。

+ +
{{EmbedInteractiveExample("pages/js/promise-constructor.html", "taller")}}
+ + + +

構文

+ +
new Promise(executor)
+
+ +

引数

+ +
+
executor
+
新しい Promise オブジェクトを構築する過程でコンストラクターによって呼び出される {{jsxref("function")}} です。 executor は結果をプロミスに結びつけるカスタムコードです。プログラマーが executor を書きます。この関数の形式は次のようなものであると期待されます。
+
+
function(resolutionFunc, rejectionFunc){
+    // 通常、いくつかの非同期操作。
+}
+
+
+
コンストラクターが新しい Promise オブジェクトを生成するとき、 resolutionFuncrejectionFunc の一対の関数も生成します。これらは Promise オブジェクトに「結束」されます。従って、 executor の中のコードが何らかの操作を実行し、その操作の結果を (値が別の Promise オブジェクトでない場合) 「満足」または「拒否」として、それぞれ resolutionFunc または rejectionFunc のどちらかを呼び出すことで反映する機会を持っています。
+
executor は意味のある返値を持ちません。これは resolutionFunc または rejectionFunc を使用することの副作用を介して通信します。この副作用とは、 Promise が「解決済み」になることです。
+
通常は、次のように動作します。 executor の内部の走査は非同期であり、コールバックを提供します。コールバックは executor のコード内で定義されます。コールバックは、 resolutionFunc を呼び出すことで終了します。 resolutionFunc の呼び出しには、引数 value が含まれます。 value は、結束された Promise オブジェクトに渡されます。 Promise オブジェクトは (非同期的に) それに関連付けられた任意の .then() を呼び出します。 .then() によって受け取った value は、 handleFulfilled の呼び出しに入力引数として渡されます (「連鎖したプロミス」の節を参照)。
+
また、 executor はエラー時に rejectionFunc を呼び出す try{} catch() ブロックを含む可能性があります。
+
これらの2つの関数の呼び出し形式は単純で、あらゆる型の引数を1つだけ取ります。もちろん、これらの関数の実際の名前は好きにしてよく、すなわち、 executor の引数として名づけます。どちらの関数も必要な時に呼び出すために使用します。
+
+ +
+
+
resolutionFunc(value) // 満足したときに呼び出される
+rejectionFunc(reason) // 拒否されたときに呼び出される
+ +

返される value は、プロミスをチェーンに動的に挿入するために、別なプロミスオブジェクトにすることができます。

+
+
+ +

返値

+ +

new を通じて呼び出された場合、 Promise コンストラクターはプロミスオブジェクトを返します。このプロミスオブジェクトは、 resolutionFunc 関数または rejectionFunc 関数が呼び出されると「解決」になります。なお、 resolutionFunc または rejectionFunc を別な Promise オブジェクトを引数にして呼び出すと、これが「解決」であると言えますが、「満足」であるとは言えません。

+ +

+ +

新しい Promise の作成

+ +

Promise オブジェクトは new キーワードとコンストラクターで作成されます。コンストラクターは executor 関数と呼ばれる引数を取ります。 executor 関数は 2 つの関数を引数として取ります。1 つめの関数 (resolve) は非同期タスクが成功して完了した場合に呼び出され、タスクの結果を値として返します。2 つめの関数 (reject) はタスクが失敗した場合に呼び出され、失敗した理由 (典型的には error オブジェクト) を返します。

+ +
const myFirstPromise = new Promise((resolve, reject) => {
+  // do something asynchronous which eventually calls either:
+  //
+  //   resolve(someValue)        // fulfilled
+  // or
+  //   reject("failure reason")  // rejected
+});
+
+ +

Promise を返す関数の作成

+ +

関数に Promise 機能を提供するには、次のように単に Promise を返すようにします。

+ +
function myAsyncFunction(url) {
+  return new Promise((resolve, reject) => {
+    const xhr = new XMLHttpRequest()
+    xhr.open("GET", url)
+    xhr.onload = () => resolve(xhr.responseText)
+    xhr.onerror = () => reject(xhr.statusText)
+    xhr.send()
+  });
+}
+ +

仕様書

+ + + + + + + + + + + + +
仕様書
{{SpecName('ESDraft', '#sec-promise-constructor', 'Promise コンストラクター')}}
+ +

ブラウザーの互換性

+ + + +

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

+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/global_objects/promise/race/index.html b/files/ja/web/javascript/reference/global_objects/promise/race/index.html new file mode 100644 index 0000000000..1ca06d96da --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/race/index.html @@ -0,0 +1,182 @@ +--- +title: Promise.race() +slug: Web/JavaScript/Reference/Global_Objects/Promise/race +tags: + - ECMAScript 2015 + - JavaScript + - Method + - Promise + - Reference + - メソッド +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/race +--- +
{{JSRef}}
+ +

Promise.race() メソッドは、反復可能オブジェクトの中の Promise のうちの1つが解決または拒否するとすぐに、その Promise の値または理由で解決または拒否する Promise を返します。

+ +
{{EmbedInteractiveExample("pages/js/promise-race.html", "taller")}}
+ + + +

構文

+ +
Promise.race(iterable);
+ +

引数

+ +
+
iterable
+
{{jsxref("Array")}} のような反復可能なオブジェクト。 iterable を確認してください。
+
+ +

返値

+ +

待ち状態の {{jsxref("Promise")}} で、反復可能オブジェクトの中で最初に解決または拒否した Promise の値を非同期に産出します。

+ +

説明

+ +

race 関数は、引数として渡された反復可能オブジェクトの中にある複数の Promise の中で解決する最初の Promise と同じ方法で解決される (同じ値を取る) Promise を返します。

+ +

渡された反復可能オブジェクトが空の場合、返される Promise はずっと待ち状態のままです。

+ +

反復可能オブジェクトに1つ以上の Promise 以外の値やすでに解決済みの Promise が含まれていた場合、 Promise.race は反復可能オブジェクトの中で見つけたこれらの値の内の最初の一つで解決します。

+ +

+ +

Promise.race の非同期性

+ +

以下の例は、 Promise.race の非同期性を示しています。

+ +
// we are passing as argument an array of promises that are already resolved,
+// to trigger Promise.race as soon as possible
+var resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];
+
+var p = Promise.race(resolvedPromisesArray);
+// immediately logging the value of p
+console.log(p);
+
+// using setTimeout we can execute code after the stack is empty
+setTimeout(function(){
+    console.log('the stack is now empty');
+    console.log(p);
+});
+
+// logs, in order:
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "fulfilled", <value>: 33 }
+ +

空の反復可能オブジェクトを渡すと、無限に解決しない Promise が返されます。

+ +
var foreverPendingPromise = Promise.race([]);
+console.log(foreverPendingPromise);
+setTimeout(function(){
+    console.log('the stack is now empty');
+    console.log(foreverPendingPromise);
+});
+
+// logs, in order:
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "pending" }
+
+ +

反復可能オブジェクトの中に1つ以上の Promise 以外の値や、すでに解決した Promise が含まれていると、 Promise.race は配列の中で見つかった最初のこれらの値で解決します。

+ +
var foreverPendingPromise = Promise.race([]);
+var alreadyFulfilledProm = Promise.resolve(100);
+
+var arr = [foreverPendingPromise, alreadyFulfilledProm, "non-Promise value"];
+var arr2 = [foreverPendingPromise, "non-Promise value", Promise.resolve(100)];
+var p = Promise.race(arr);
+var p2 = Promise.race(arr2);
+
+console.log(p);
+console.log(p2);
+setTimeout(function(){
+    console.log('the stack is now empty');
+    console.log(p);
+    console.log(p2);
+});
+
+// logs, in order:
+// Promise { <state>: "pending" }
+// Promise { <state>: "pending" }
+// the stack is now empty
+// Promise { <state>: "fulfilled", <value>: 100 }
+// Promise { <state>: "fulfilled", <value>: "non-Promise value" }
+
+ +

Promise.race の使用 – setTimeout を使用した例

+ +
var p1 = new Promise(function(resolve, reject) {
+    setTimeout(() => resolve('one'), 500);
+});
+var p2 = new Promise(function(resolve, reject) {
+    setTimeout(() => resolve('two'), 100);
+});
+
+Promise.race([p1, p2])
+.then(function(value) {
+  console.log(value); // "two"
+  // Both fulfill, but p2 is faster
+});
+
+var p3 = new Promise(function(resolve, reject) {
+    setTimeout(() => resolve('three'), 100);
+});
+var p4 = new Promise(function(resolve, reject) {
+    setTimeout(() => reject(new Error('four')), 500);
+});
+
+Promise.race([p3, p4])
+.then(function(value) {
+  console.log(value); // "three"
+  // p3 is faster, so it fulfills
+}, function(reason) {
+  // Not called
+});
+
+var p5 = new Promise(function(resolve, reject) {
+    setTimeout(() => resolve('five'), 500);
+});
+var p6 = new Promise(function(resolve, reject) {
+    setTimeout(() => reject(new Error('six')), 100);
+});
+
+Promise.race([p5, p6])
+.then(function(value) {
+  // Not called
+}, function(error) {
+  console.log(error.message); // "six"
+  // p6 is faster, so it rejects
+});
+
+ +

仕様書

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

ブラウザーの互換性

+ + + +

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

+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/global_objects/promise/reject/index.html b/files/ja/web/javascript/reference/global_objects/promise/reject/index.html new file mode 100644 index 0000000000..f59d0bea93 --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/reject/index.html @@ -0,0 +1,74 @@ +--- +title: Promise.reject() +slug: Web/JavaScript/Reference/Global_Objects/Promise/reject +tags: + - ECMAScript 2015 + - JavaScript + - Method + - Promise + - Reference +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/reject +--- +
{{JSRef}}
+ +

Promise.reject() メソッドは、引数で与えられた理由でリジェクトされた Promise オブジェクトを返します。

+ +
{{EmbedInteractiveExample("pages/js/promise-reject.html")}}
+ + + +

構文

+ +
Promise.reject(reason);
+ +

引数

+ +
+
reason
+
このPromiseオブジェクトのリジェクトされた理由
+
+ +

返値

+ +

与えられた理由で拒否された {{jsxref("Promise")}} 。

+ +

解説

+ +

静的な Promise.reject 関数は拒否された Promise を返します。デバッグのためにキャッチするエラーを選別したい場合は、 reasoninstanceof {{jsxref("Error")}} にかけると良いでしょう。

+ +

+ +

静的な Promise.reject() メソッドの使用

+ +
Promise.reject(new Error('fail')).then(function() {
+  // ここは呼ばれません。
+}, function(error) {
+  console.error(error); // Stacktrace
+});
+ +

仕様書

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

ブラウザーの互換性

+ + + +

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

+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/global_objects/promise/resolve/index.html b/files/ja/web/javascript/reference/global_objects/promise/resolve/index.html new file mode 100644 index 0000000000..4584bdf8be --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/resolve/index.html @@ -0,0 +1,139 @@ +--- +title: Promise.resolve() +slug: Web/JavaScript/Reference/Global_Objects/Promise/resolve +tags: + - ECMAScript 2015 + - JavaScript + - Method + - Promise + - Reference +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/resolve +--- +
{{JSRef}}
+ +

Promise.resolve() メソッドは、与えられた値で解決した {{jsxref("Promise")}} オブジェクトを返します。その値がプロミスであった場合は、そのプロミスが返されます。その値が thenable (すなわち {{jsxref("Promise.then", "\"then\" メソッド")}} を持っている場合) であれば、返されるプロミスは thenable を「追跡」し、その最終的な状態を採用します。それ以外の場合は、引数で満足したプロミスが返されます。この関数は複数階層のプロミス風オブジェクト (例えば、何かで解決するプロミスで解決するプロミス) を単一の階層に平坦化します。

+ +

構文

+ +
Promise.resolve(value);
+
+ +

引数

+ +
+
value
+
この Promise で解決する際の引数。解決するための Promise または thenable にすることもできます。
+
+ +

返値

+ +

与えられた値で解決された {{jsxref("Promise")}}、または value がプロミスオブジェクトであった場合、値として渡されたプロミスです。

+ +

解説

+ +

静的な Promise.resolve 関数は、解決する Promise を返します。

+ +

+ +

静的な Promise.resolve メソッドの使用

+ +
Promise.resolve('Success').then(function(value) {
+  console.log(value); // "Success"
+}, function(value) {
+  // not called
+});
+
+ +

配列で解決

+ +
var p = Promise.resolve([1,2,3]);
+p.then(function(v) {
+  console.log(v[0]); // 1
+});
+
+ +

別の Promise で解決

+ +
var original = Promise.resolve(33);
+var cast = Promise.resolve(original);
+cast.then(function(value) {
+  console.log('value: ' + value);
+});
+console.log('original === cast ? ' + (original === cast));
+
+// ログの順番:
+// original === cast ? true
+// value: 33
+
+ +

ログの順番が反転するのは、 then ハンドラーが非同期に呼び出されるために発生します。 then がどのように動作するのかはこちらを参照してください。

+ +

thenables で解決してエラーを発生させる

+ +
// Resolving a thenable object
+var p1 = Promise.resolve({
+  then: function(onFulfill, onReject) { onFulfill('fulfilled!'); }
+});
+console.log(p1 instanceof Promise) // true, object casted to a Promise
+
+p1.then(function(v) {
+    console.log(v); // "fulfilled!"
+  }, function(e) {
+    // not called
+});
+
+// Thenable throws before callback
+// Promise rejects
+var thenable = { then: function(resolve) {
+  throw new TypeError('Throwing');
+  resolve('Resolving');
+}};
+
+var p2 = Promise.resolve(thenable);
+p2.then(function(v) {
+  // not called
+}, function(e) {
+  console.error(e); // TypeError: Throwing
+});
+
+// Thenable throws after callback
+// Promise resolves
+var thenable = { then: function(resolve) {
+  resolve('Resolving');
+  throw new TypeError('Throwing');
+}};
+
+var p3 = Promise.resolve(thenable);
+p3.then(function(v) {
+  console.log(v); // "Resolving"
+}, function(e) {
+  // not called
+});
+
+ +

仕様書

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

ブラウザーの互換性

+ + + +

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

+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/global_objects/promise/then/index.html b/files/ja/web/javascript/reference/global_objects/promise/then/index.html new file mode 100644 index 0000000000..323e7e874f --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/promise/then/index.html @@ -0,0 +1,300 @@ +--- +title: Promise.prototype.then() +slug: Web/JavaScript/Reference/Global_Objects/Promise/then +tags: + - ECMAScript 2015 + - JavaScript + - Method + - Promise + - Prototype +translation_of: Web/JavaScript/Reference/Global_Objects/Promise/then +--- +
{{JSRef}}
+ +

then() メソッドは {{jsxref("Promise")}} を返します。最大2つの引数、 Promise が成功した場合と失敗した場合のコールバック関数を取ります。

+ +
{{EmbedInteractiveExample("pages/js/promise-then.html")}}
+ + + +
+

片方または両方の引数が省略されたり、関数ではないものが渡されたりした場合、 then にはハンドラーが不足しますが、エラーは発生しません。 Promise が状態 (fulfillment (完了) または rejection (拒否)) を受け入れるに当たって then が呼び出された際に、 then がハンドラーを持たない場合は、 then が呼び出された元の Promise の最後の状態を受け入れた、追加のハンドラーのない新しい Promise が生成されます。

+
+ +

構文

+ +
p.then(onFulfilled[, onRejected]);
+
+p.then(value => {
+  // fulfillment
+}, reason => {
+  // rejection
+});
+
+ +

引数

+ +
+
onFulfilled {{optional_inline}}
+
Promise が成功したときに呼び出される {{jsxref("Function")}} です。この関数は1つの引数、 fulfillment value を持ちます。これが関数ではない場合は、内部的に "Identity" 関数 (受け取った引数を返す関数) に置き換えられます。
+
onRejected {{optional_inline}}
+
Promise が拒絶されたときに呼び出される {{jsxref("Function")}} です。この関数は1つの引数、 rejection reason を持ちます。これが関数ではない場合は、内部的に "Thrower" 関数 (引数として受け取ったエラーを投げる関数) に置き換えられます。
+
+ +

返値

+ +

{{jsxref("Promise")}} が完了するか拒否されると、それぞれのハンドラー関数 (onFulfilled または onRejected) が非同期に呼び出されます (現在のスレッドループにスケジュールされます)。ハンドラー関数のこの動作は特定の一連の規則に従います。もしハンドラー関数が・・・

+ + + +

以下は、 then メソッドの非同期性を示す例です。

+ +
// using a resolved promise, the 'then' block will be triggered instantly,
+// but its handlers will be triggered asynchronously as demonstrated by the console.logs
+const resolvedProm = Promise.resolve(33);
+
+let thenProm = resolvedProm.then(value => {
+    console.log("this gets called after the end of the main stack. the value received and returned is: " + value);
+    return value;
+});
+// instantly logging the value of thenProm
+console.log(thenProm);
+
+// using setTimeout we can postpone the execution of a function to the moment the stack is empty
+setTimeout(() => {
+    console.log(thenProm);
+});
+
+
+// logs, in order:
+// Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
+// "this gets called after the end of the main stack. the value received and returned is: 33"
+// Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 33}
+ +

説明

+ +

then メソッドや {{jsxref("Promise.prototype.catch()")}} メソッドは Promise を返すので、チェーン可能です。 — これは composition と呼ばれる操作です。

+ +

+ +

then メソッドの使用

+ +
var p1 = new Promise((resolve, reject) => {
+  resolve('Success!');
+  // or
+  // reject(new Error("Error!"));
+});
+
+p1.then(value => {
+  console.log(value); // Success!
+}, reason => {
+  console.error(reason); // Error!
+} );
+
+ +

チェーン

+ +

then メソッドは Promise を返すので、メソッドチェーンができます。

+ +

関数が then にハンドラーとして渡されると Promise を返します。同じ Promise がメソッドチェーンの次の then に現れます。次のスニペットは、非同期実行をシミュレートする、 setTimeout() 関数付きのコードです。

+ +
Promise.resolve('foo')
+  // 1. Receive "foo", concatenate "bar" to it, and resolve that to the next then
+  .then(function(string) {
+    return new Promise(function(resolve, reject) {
+      setTimeout(function() {
+        string += 'bar';
+        resolve(string);
+      }, 1);
+    });
+  })
+  // 2. receive "foobar", register a callback function to work on that string
+  // and print it to the console, but not before returning the unworked on
+  // string to the next then
+  .then(function(string) {
+    setTimeout(function() {
+      string += 'baz';
+      console.log(string); // foobarbaz
+    }, 1)
+    return string;
+  })
+  // 3. print helpful messages about how the code in this section will be run
+  // before the string is actually processed by the mocked asynchronous code in the
+  // previous then block.
+  .then(function(string) {
+    console.log("Last Then:  oops... didn't bother to instantiate and return " +
+                "a promise in the prior then so the sequence may be a bit " +
+                "surprising");
+
+    // Note that `string` will not have the 'baz' bit of it at this point. This
+    // is because we mocked that to happen asynchronously with a setTimeout function
+    console.log(string); // foobar
+  });
+
+// logs, in order:
+// Last Then: oops... didn't bother to instantiate and return a promise in the prior then so the sequence may be a bit surprising
+// foobar
+// foobarbaz
+ +

then() の引数として渡された関数(ハンドラ)が値を返した場合は、 Promise.resolve (<ハンドラーが呼ばれて返された値>) によって、返値を自動的に Promise でラップします。

+ +
var p2 = new Promise(function(resolve, reject) {
+  resolve(1);
+});
+
+p2.then(function(value) {
+  console.log(value); // 1
+  return value + 1;
+}).then(function(value) {
+  console.log(value + ' - A synchronous value works'); // 2 - A synchronous value works
+});
+
+p2.then(function(value) {
+  console.log(value); // 1
+});
+
+ +

then の引数として渡した関数が拒絶された Promise が返した場合や、例外 (エラー) が発生した場合は、拒絶された Promise を返します。

+ +
Promise.resolve()
+  .then(() => {
+    // Makes .then() return a rejected promise
+    throw new Error('Oh no!');
+  })
+  .then(() => {
+    console.log('Not called.');
+  }, error => {
+    console.error('onRejected function called: ' + error.message);
+  });
+ +

その他の場合はすべて、解決中 (resolving) の Promise が返されます。次の例では、チェーン上の以前の Promise が拒絶されていても、最初の then() は解決中の Promise に含まれた 42 を返します。

+ +
Promise.reject()
+  .then(() => 99, () => 42) // onRejected returns 42 which is wrapped in a resolving Promise
+  .then(solution => console.log('Resolved with ' + solution)); // Resolved with 42
+ +

多くの場合、 catch を使って失敗状態の Promise を補足する方が、 then の 2 つのハンドラーを使って処理するよりも現実的です。下記の例を見てください。

+ +
Promise.resolve()
+  .then(() => {
+    // Makes .then() return a rejected promise
+    throw new Error('Oh no!');
+  })
+  .catch(error => {
+    console.error('onRejected function called: ' + error.message);
+  })
+  .then(() => {
+    console.log("I am always called even if the prior then's promise rejects");
+  });
+ +

Promise ベースの API を持った関数同士であれば、別の関数上に他の関数を実装することでチェーンを使うこともできます。

+ +
function fetch_current_data() {
+  // The fetch() API returns a Promise.  This function
+  // exposes a similar API, except the fulfillment
+  // value of this function's Promise has had more
+  // work done on it.
+  return fetch('current-data.json').then(response => {
+    if (response.headers.get('content-type') != 'application/json') {
+      throw new TypeError();
+    }
+    var j = response.json();
+    // maybe do something with j
+    return j; // fulfillment value given to user of
+              // fetch_current_data().then()
+  });
+}
+
+ +

onFulfilled がプロミスを返した場合、 then の返値はプロミスによって解決/拒否されます。

+ +
function resolveLater(resolve, reject) {
+  setTimeout(function() {
+    resolve(10);
+  }, 1000);
+}
+function rejectLater(resolve, reject) {
+  setTimeout(function() {
+    reject(new Error('Error'));
+  }, 1000);
+}
+
+var p1 = Promise.resolve('foo');
+var p2 = p1.then(function() {
+  // Return promise here, that will be resolved to 10 after 1 second
+  return new Promise(resolveLater);
+});
+p2.then(function(v) {
+  console.log('resolved', v);  // "resolved", 10
+}, function(e) {
+  // not called
+  console.error('rejected', e);
+});
+
+var p3 = p1.then(function() {
+  // Return promise here, that will be rejected with 'Error' after 1 second
+  return new Promise(rejectLater);
+});
+p3.then(function(v) {
+  // not called
+  console.log('resolved', v);
+}, function(e) {
+  console.error('rejected', e); // "rejected", 'Error'
+});
+
+ +

window.setImmediate 形式のプロミスベースの代替処理

+ +

{{jsxref("Function.prototype.bind()")}} を使用して、 Reflect.apply ({{jsxref("Reflect.apply()")}}) メソッドは (キャンセルできない) {{domxref("window.setImmediate")}} 形式の関数を作成することができます。

+ +
const nextTick = (() => {
+  const noop = () => {}; // literally
+  const nextTickPromise = () => Promise.resolve().then(noop);
+
+  const rfab = Reflect.apply.bind; // (thisArg, fn, thisArg, [...args])
+  const nextTick = (fn, ...args) => (
+    fn !== undefined
+    ? Promise.resolve(args).then(rfab(null, fn, null))
+    : nextTickPromise(),
+    undefined
+  );
+  nextTick.ntp = nextTickPromise;
+
+  return nextTick;
+})();
+
+ +

仕様書

+ + + + + + + + + + + + +
仕様書
{{SpecName('ESDraft', '#sec-promise.prototype.then', 'Promise.prototype.then')}}
+ +

ブラウザーの互換性

+ + + +

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

+ +

関連情報

+ + -- cgit v1.2.3-54-g00ecf