Skip to content

Commit cec882a

Browse files
committed
feat(ch2): Promise#finallyのチャプターを追加
1 parent 33b87dc commit cec882a

File tree

3 files changed

+102
-5
lines changed

3 files changed

+102
-5
lines changed

Ch2_HowToWrite/promise-and-array.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[[ch2-promise-and-array]]
22
== Promiseと配列
33

4-
ここまでで、promiseオブジェクトが FulFilled または Rejected となった時の処理は <<promise.then,`.then`>> と <<promise.catch,`.catch`>> で登録できることを学びました
4+
ここまでで、promiseオブジェクトが FulFilled または Rejected となった時の処理は <<promise.then,`.then`>> と <<promise.catch,`.catch`>> で登録でき、 <<promise.finally,`.finally`>> を使うことで FulFilled と Rejected どちらの場合でも実行される処理を登録できることを学びました
55

66
一つのpromiseオブジェクトなら、そのpromiseオブジェクトに対して処理を書けばよいですが、
77
複数のpromiseオブジェクトが全てFulFilledとなった時の処理を書く場合はどうすればよいでしょうか?
Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,101 @@
11
[[ch2-promise-finally]]
22
== Promise#finally
33

4-
- Promise#finnalyの使い方
5-
- ユースケース
6-
- Promiseを返す、promiseチェーンの状態を維持する
7-
- 割り込めるけど、名前通り最後にしたほうがいい
4+
ECMAScript 2018からpromise chainの最後に処理を実行する `Promise#finally` メソッド追加されました。
5+
6+
`Promise#finally` メソッドは成功時、失敗時どちらの場合でも呼び出すコールバック関数を登録できます。
7+
`try...catch...finally` 構文の `finally` 節と同様の役割をもつメソッドです。
8+
9+
次のコードのように、 `Promise#finally` メソッドで登録したコールバック関数は、promiseオブジェクトが *resolve*(成功) / *reject*(失敗) どちらの場合でも呼ばれます。
10+
11+
[role="executable"]
12+
[source,javascript]
13+
.finallyのコード例
14+
----
15+
Promise.resolve("成功").finally(function(){
16+
console.log("成功時に実行される");
17+
});
18+
Promise.reject(new Error("失敗")).finally(function(){
19+
console.log("失敗時に実行される");
20+
});
21+
----
22+
23+
`finally` メソッドのコールバック関数は引数を受け取らず、どのような値を返してもpromise chainには影響を与えません。
24+
また、 `finally` メソッドも新しいpromiseオブジェクトを返し、新しいpromiseオブジェクトは呼び出し元のpromiseオブジェクトの状態をそのまま引き継ぎます。
25+
26+
`Promise#finally(onFinally)` は、`Promise#then` メソッドで書くと次のように書けます。
27+
28+
[role="executable"]
29+
[source,javascript]
30+
.finallyをthenで表現
31+
----
32+
function onFinally() {
33+
// 成功、失敗どちらでも実行したい処理
34+
}
35+
36+
// `Promise#finally` は新しいpromiseオブジェクトを返す
37+
Promise.resolve(42).finally(function(){
38+
onFinally()
39+
}).then(function(value) {
40+
// 呼び出し元のpromiseオブジェクトの状態をそのまま引き継ぐ
41+
// 呼び出し元のpromiseオブジェクトは `42` で resolveされている
42+
console.log(value); // 42
43+
})
44+
45+
// Promise#thenでの同等の表現
46+
promise.then(function(result) {
47+
onFinally();
48+
return result;
49+
}, function(error) {
50+
onFinally();
51+
throw error;
52+
});
53+
----
54+
55+
56+
`Promise#finally` メソッドを使うことで、promise chainで必ず実行したい処理を簡単に書けるようになっています。
57+
58+
次のコードでは、リソースを取得中かどうかを判定するためのフラグを `isLoading` という変数で管理しています。
59+
`Promise#finally` メソッドを使い成功失敗どちらにもかかわらず、取得が終わったら `isLoading` は `false` にしています。
60+
61+
[role="executable"]
62+
[source,javascript]
63+
.finallyのユースケース
64+
----
65+
// リソースを取得中かどうかのフラグ
66+
var isLoading = false
67+
function getResource(URL) {
68+
// リソース取得中フラグをON
69+
isLoading = false
70+
return new Promise(function (resolve, reject) {
71+
var req = new XMLHttpRequest();
72+
req.open('GET', URL, true);
73+
req.onload = function () {
74+
if (req.status === 200) {
75+
resolve(req.responseText);
76+
} else {
77+
reject(new Error(req.statusText));
78+
}
79+
};
80+
req.onerror = function () {
81+
reject(new Error(req.statusText));
82+
};
83+
req.send();
84+
}).finally(function(){
85+
// リソース取得に成功/失敗どちらの場合も取得中フラグをOFF
86+
isLoading = false;
87+
});
88+
}
89+
90+
console.log("リソースロード開始", isLoading);
91+
getResource("https://httpbin.org/get").then(function(value) {
92+
console.log("リソース成功", isLoading);
93+
console.log(value);
94+
}).catch(function(error) {
95+
console.log("リソース失敗", isLoading);
96+
console.error(error);
97+
});
98+
console.log("リソースロード中", isLoading);
99+
----
100+
101+
`then` と `catch` メソッドでも実現できますが、 `Promise#finally` メソッドを使うことで `isLoading` の代入を一箇所にまとめられます。

Ch2_HowToWrite/readme.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ include::promise-then.adoc[]
1919
// Promise#catch
2020
include::promise-catch.adoc[]
2121

22+
// Promise#finally
23+
include::promise-finally.adoc[]
24+
2225
// コラム: `then` は常に新しいpromiseオブジェクトを返す
2326
include::then-return-new-promise.adoc[]
2427

0 commit comments

Comments
 (0)