-
-
Notifications
You must be signed in to change notification settings - Fork 575
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
591 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
[async-function-await] | ||
== ``await``式 | ||
|
||
Async Functionのことは一般的にasync/awaitとも呼ばれることがあります。 | ||
この呼ばれ方からもわかるようにAsync Functionにおける``await``式は重要な役割を持っています。 | ||
|
||
``await``式はAsync Functionの関数内でのみ利用できます。 | ||
``await``式は右辺の``Promise``インスタンスが**Fulfilled**または**Rejected**になるまでその場で非同期処理の完了を待ちます。 | ||
そして``Promise``インスタンスの状態が変わると、処理を再開します。 | ||
|
||
|
||
[source,js] | ||
---- | ||
async function asyncMain() { | ||
// PromiseがFulfilledまたはRejectedとなるまで待つ | ||
await Promiseインスタンス; | ||
// Promiseインスタンスの状態が変わったら処理を再開する | ||
} | ||
---- | ||
|
||
普通の処理の流れでは、非同期処理を実行した場合にその非同期処理の完了を待つことなく、次の行(次の文)を実行します。 | ||
しかし``await``式では非同期処理を実行し完了するまで、次の行(次の文)を実行しません。 | ||
そのため``await``式を使うことで非同期処理が同期処理のように上から下へと順番に実行するような処理順で書けます。 | ||
|
||
|
||
[source,js] | ||
---- | ||
// async functionは必ずPromiseを返す | ||
async function doAsync() { | ||
// 非同期処理 | ||
} | ||
async function asyncMain() { | ||
// doAsyncの非同期処理が完了するまでまつ | ||
await doAsync(); | ||
// 次の行はdoAsyncの非同期処理が完了されるまで実行されない | ||
console.log("この行は非同期処理が完了後に実行される"); | ||
} | ||
---- | ||
|
||
``await``式は**式**であるため右辺(``Promise``インスタンス)の評価結果を値として返します。 | ||
この``await``式の評価方法は評価するPromiseの状態(**Fulfilled**または**Rejected**)によって異なります。 | ||
|
||
``await``式の右辺のPromiseが**Fulfilled**となった場合は、resolveされた値が``await``式の返り値となります。 | ||
|
||
次のコードでは、``await``式の右辺にある``Promise``インスタンスは``42``という値でresolveされています。 | ||
そのため``await``式の返り値は``42``となり、``value``変数にもその値が入ります。 | ||
|
||
[role="executable"] | ||
[source,javascript] | ||
---- | ||
async function asyncMain() { | ||
const value = await Promise.resolve(42); | ||
console.log(value); // => 42 | ||
} | ||
asyncMain(); // Promiseインスタンスを返す | ||
---- | ||
|
||
これはPromiseを使って書くと次のコードと同様の意味となります。 | ||
``await``式を使うことでコールバック関数を使わずに非同期処理の流れを表現できていることがわかります。 | ||
|
||
[role="executable"] | ||
[source,javascript] | ||
---- | ||
function asyncMain() { | ||
return Promise.resolve(42).then(value => { | ||
console.log(value); // => 42 | ||
}); | ||
} | ||
asyncMain(); // Promiseインスタンスを返す | ||
---- | ||
|
||
``await``式の右辺のPromiseが**Rejected**となった場合は、その場でエラーを``throw``します。 | ||
またAsync Function内で発生した例外は自動的にキャッチされます。 | ||
そのため``await``式でPromiseが**Rejected**となった場合は、そのAsync Functionが**Rejected**なPromiseを返すことになります。 | ||
|
||
次のコードでは、``await``式の右辺にある``Promise``インスタンスが**Rejected**の状態になっています。 | ||
そのため``await``式は``エラー``を``throw``するため、``asyncMain``関数は**Rejected**なPromiseを返します。 | ||
|
||
[role="executable"] | ||
[source,javascript] | ||
---- | ||
async function asyncMain() { | ||
const value = await Promise.reject(new Error("エラーメッセージ")); | ||
// await式で例外が発生したため、この行は実行されません | ||
} | ||
// Async Functionは自動的に例外をキャッチできる | ||
asyncMain().catch(error => { | ||
console.log(error.message); // => "エラーメッセージ" | ||
}); | ||
---- | ||
|
||
``await``式がエラーを``throw``するということは、そのエラーは``try...catch``構文でキャッチできます。 | ||
通常の非同期処理では完了する前に次の行が実行されてしまうため``try...catch``構文ではエラーをキャッチできませんでした。 | ||
そのためPromiseでは``catch``メソッドを使いPromise内で発生したエラーをキャッチしていました。(<<promise-done,Promise.prototype.done とは何か?>>を参照) | ||
|
||
次のコードでは、``await``式で発生した例外を``try...catch``構文でキャッチしています。 | ||
|
||
{{book.console}} | ||
// doctest:async:16 | ||
|
||
[source,js] | ||
---- | ||
async function asyncMain() { | ||
// await式のエラーはtry...catchできる | ||
try { | ||
const value = await Promise.reject(new Error("エラーメッセージ")); | ||
// await式で例外が発生したため、この行は実行されません | ||
} catch (error) { | ||
console.log(error.message); // => "エラーメッセージ" | ||
} | ||
} | ||
asyncMain().catch(error => { | ||
// すでにtry...catchされているため、この行は実行されません | ||
}); | ||
---- | ||
|
||
このように``await``式を使うことで、``try...catch``構文のように非同期処理を同期処理と同じ構文を使って扱えます。 | ||
またコードの見た目も同期処理と同じように、その行(その文)の処理が完了するまで次の行を評価しないという分かりやすい形になるのは大きな利点です。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
[async-function-syntax] | ||
== Async Functionの構文 | ||
|
||
Async Functionは関数の定義に``async``キーワードをつけることで定義できます。 | ||
JavaScriptの関数定義には関数宣言や関数式、Arrow Function、メソッドの短縮記法などがあります。 | ||
どの定義方法でも``async``キーワードを前につけるだけでAsync Functionとして定義できます。 | ||
|
||
[role="executable"] | ||
[source,javascript] | ||
---- | ||
// 関数宣言のAsync Function版 | ||
async function fn1() {} | ||
// 関数式のAsync Function版 | ||
const fn2 = async function() {}; | ||
// Arrow FunctionのAsync Function版 | ||
const fn3 = async() => {}; | ||
// メソッドの短縮記法のAsync Function版 | ||
const object = { async method() {} }; | ||
---- | ||
|
||
これらのAsync Functionは、必ずPromiseを返すことや関数中では``await``式が利用できること以外は、通常の関数と同じ性質を持ちます。 | ||
|
||
[#async-function-return-promise] | ||
== Async FunctionはPromiseを返す | ||
|
||
Async Functionとして定義した関数は必ず``Promise``インスタンスを返します。 | ||
具体的にはAsync Functionが返す値は次の3つのケースが考えられます。 | ||
|
||
1. Async Functionは値をreturnした場合、その返り値をもつ**Fulfilled**なPromiseを返す | ||
2. Async FunctionがPromiseをreturnした場合、その返り値のPromiseをそのまま返す | ||
3. Async Function内で例外が発生した場合は、そのエラーをもつ**Rejected**なPromiseを返す | ||
|
||
次のコードでは、Async Functionがそれぞれの返り値によってどのような``Promise``インスタンスを返すかを確認できます。 | ||
これらの挙動は``Promise#then``メソッドの返り値とそのコールバック関数が返す値の関係とほぼ同じです。 | ||
|
||
[role="executable"] | ||
[source,javascript] | ||
---- | ||
// 1. resolveFnは値を返している | ||
// 何もreturnしていない場合はundefinedを返したのと同じ扱いとなる | ||
async function resolveFn() { | ||
return "返り値"; | ||
} | ||
resolveFn().then(value => { | ||
console.log(value); // => "返り値" | ||
}); | ||
// 2. rejectFnはPromiseインスタンスを返している | ||
async function rejectFn() { | ||
return Promise.reject(new Error("エラーメッセージ")); | ||
} | ||
// rejectFnはRejectedなPromiseを返すのでcatchできる | ||
rejectFn().catch(error => { | ||
console.log(error.message); // => "エラーメッセージ" | ||
}); | ||
// 3. exceptionFnは例外を投げている | ||
async function exceptionFn() { | ||
throw new Error("例外が発生しました"); | ||
// 例外が発生したため、この行は実行されません | ||
} | ||
// Async Functionで例外が発生するとRejectedなPromiseが返される | ||
exceptionFn().catch(error => { | ||
console.log(error.message); // => "例外が発生しました" | ||
}); | ||
---- | ||
|
||
どの場合でもAsync Functionは必ずPromiseを返すことがわかります。 | ||
このようにAsync Functionを呼び出す側から見れば、Async FunctionはPromiseを返すただの関数と何も変わりません。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
[[async-function]] | ||
== Async Functionとは | ||
|
||
Async Functionとは非同期処理を行う関数を定義する構文です。 | ||
Async Functionは通常の関数とは異なり、必ず``Promise``インスタンスを返す関数を定義する構文です。 | ||
|
||
Async Functionは次のように関数の前に``async``をつけることで定義できます。 | ||
この``doAsync``関数は常に``Promise``インスタンスを返します。 | ||
|
||
[role="executable"] | ||
[source,javascript] | ||
---- | ||
async function doAsync() { | ||
return "値"; | ||
} | ||
// doAsync関数はPromiseを返す | ||
doAsync().then(value => { | ||
console.log(value); // => "値" | ||
}); | ||
---- | ||
|
||
Async Functionでは``return``した値の代わりに、``Promise.resolve(返り値)``のように返り値をラップした``Promise``インスタンスを返します。 | ||
そのため、このAsync Functionは次のように書いた場合と同じ意味になります。 | ||
|
||
[role="executable"] | ||
[source,javascript] | ||
---- | ||
// 通常の関数でPromiseインスタンスを返している | ||
function doAsync() { | ||
return Promise.resolve("値"); | ||
} | ||
doAsync().then(value => { | ||
console.log(value); // => "値" | ||
}); | ||
---- | ||
|
||
またAsync Function内では``await``式というPromiseの非同期処理が完了するまで待つ構文が利用できます。 | ||
``await``式を使うことで非同期処理を同期処理のように扱えるため、Promiseチェーンで実現していた処理の流れを読みやすくかけます。 | ||
|
||
まずは、Async Functionと``await``式を使った場合はどのように書けるかを簡単に見ていきます。 | ||
|
||
次の例ではFetch APIで``/json/book.json``を取得して、``title``を取り出す``getBookTitle``関数の実行結果をコンソールに出力しています。 | ||
取得``book.json``は次のような内容になっています。 | ||
|
||
[[book.json]] | ||
./json/book.json | ||
[source,json] | ||
---- | ||
include::../json/book.json[] | ||
---- | ||
|
||
次のコードでは、Promiseのみを使って`getBookTitle``関数で取得したタイトルをコンソールに出力しています。 | ||
|
||
[role="executable"] | ||
[source,javascript] | ||
---- | ||
function getBookTitle(){ | ||
return fetch("/json/book.json").then(function(res){ | ||
return res.json(); // レスポンスをJSON形式としてパースする | ||
}).then(json => { | ||
return json.title; // JSONからtitleプロパティを取り出す | ||
}); | ||
} | ||
function main(){ | ||
getBookTitle().then(function(title) => { | ||
console.log(title); // => "JavaScript Promiseの本" | ||
}); | ||
} | ||
main(); | ||
---- | ||
|
||
次のコードでは、Async Functionと``await``式を使って`getBookTitle``関数で取得したタイトルをコンソールに出力しています。 | ||
|
||
[role="executable"] | ||
[source,javascript] | ||
---- | ||
function getBookTitle(){ | ||
return fetch("/json/book.json").then(function(res){ | ||
return res.json(); // レスポンスをJSON形式としてパースする | ||
}).then(json => { | ||
return json.title; // JSONからtitleプロパティを取り出す | ||
}); | ||
} | ||
// `async`をつけてAsync Functionを定義 | ||
async function main(){ | ||
// `await`式で`getBookTitle`の非同期処理が完了するまで待つ | ||
// `getBookTitle`がresolveした値が返り値になる | ||
const title = await getBookTitle(); | ||
console.log(title); // => "JavaScript Promiseの本" | ||
} | ||
main(); | ||
---- | ||
|
||
Async Functionでは非同期処理が完了するまで待つ``await``式を使うことができます。 | ||
これにより、Promiseでは結果を``then``メソッドのコールバック関数で取得していたのが、``await``式によって同期的な関数のように結果を受け取れます。 | ||
このように、Async Functionと``await``式を使うことで非同期処理をまるで同期処理のように書けます。 | ||
|
||
この章では、Async Functionと``await``式について見ていきます。 | ||
|
||
重要なこととしてAsync FunctionはPromiseの上に作られた構文です。 | ||
そのためAsync Functionを理解するには、Promiseを理解する必要があることに注意してください。 |
Oops, something went wrong.