まず前提として、async関数の戻す値は遅延しているので、関数から返ってくるタイミングと同じタイミングで受け取ることはできないということがあります。
例ですが、たとえばawait sleep(1000);すると1秒待つsleep関数があるとします。
async function f() {
await sleep(1000);
return "hello";
}
const data = f();
// このタイミング
このdataを、すぐに(f()を呼んだのと同じタイミングで)使うことはできません。なぜなら、await sleep(1000);しているために、値が決まるのは1秒後になるからです。
このような、「値は後で決まるが、値の箱は返しておきたい」という目的のためにあるのがPromiseオブジェクトです。
Promiseオブジェクトから値を取り出す方法は主に2つあります。
-
then()メソッド
- async関数の中で
awaitする・・・これはthen()メソッドとやっていることは同じです
then()メソッドの使い方ですが、以下のようです。
data.then(result => {
console.log(result); //=> hello
});
単純ですね。重要な事実として、thenに渡したコールバックの中のコードはいつ実行されるかわからない(基本的に、遅れる)し、処理が失敗すれば実行されないということがあります。
async関数の中でawaitする方法は以下のようになります。
async g() {
const result = await data;
}
g();
蛇足
sleep()関数は以下のようにすると作ることができます。
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
以下のコードで、1秒後にhelloと表示されます。
async function f() {
await sleep(1000);
return "hello";
}
f().then(result => console.log(result));
追記
普通のJavaScriptのコードは、エラーを吐くことがあります。
それと同じように、Promiseの処理は失敗することがあるという意味です。
実は、awaitというのはPromiseから値を取り出す操作です。Promiseが失敗していれば、awaitは失敗して、エラーを吐きます。
エラーを吐けば、もしtry-catchで囲んでいなければ処理は強制終了になります。
async function f() {
var data = await hoge();
let newData = data.json();
}
この例では、hoge()の結果が失敗していれば、dataに代入される前にawaitが失敗してエラーを吐き、その後の処理は実行されません。
もし、hoge()が失敗する可能性があり、失敗した場合も何かをしたいなら、以下のような書き方ができます。
async function f() {
try {
var data = await hoge();
let newData = data.json();
} catch (reason) {
// 失敗した場合
}
}
また、
いつ実行されるかわからない
というのは、基本的には非同期処理が完了して値が決まったタイミングで実行されるが、タイマー処理でもなければそのタイミングがいつか予測するのは難しいという意味です(HTTPで取得する処理など)