async/await
について勝手に誤解していたこと。
Promise
まわりの記述を置き換えるわけじゃない
なんか勝手にそう思ってたので飲み込めてなかった。
async
はreturn new Promise
とおなじこと ...正しいようで違う
以下のコードでは「同じ」ように振舞う。
let f1 = () => {
return new Promise((resolve) => {
return 'resolved';
});
}
let f2 = async () => {
return 'resolved';
}
// f1() == Promise { 'resolved' }
// f2() == Promise { 'resolved' }
が、それは非同期処理をしていないから。現実にはPromise
を使うなら必ず非同期処理をするから、以下のポイントが重要になる。
async
中のreturn
はresolve
と同じように使える ...間違い
下のコードでf4
の戻り値がPromise { undefined }
になっていることからわかるように、async
関数はresolve
と違い、非同期のreturn
を待ってくれるわけではない。
let p1 = new Promise((resolve) => {
resolve('resolved');
});
let f3 = async () => {
let p1Text = await p1;
console.log(`f3: ${p1Text}`);
return p1Text;
};
let f4 = async () => {
p1.then((p1Text) => {
console.log(`f4: ${p1Text}`);
return p1Text;
});
};
let f5 = () => {
return new Promise((resolve) => {
p1.then((p1Text) => {
console.log(`f5: ${p1Text}`);
resolve(p1Text);
});
});
};
let f3Result = f3();
let f4Result = f4();
let f5Result = f5();
console.log([f3Result, f4Result, f5Result]);
Promise.all([f3Result, f4Result, f5Result]).then((results) => {
console.log(results);
});
// 実行結果
// [ Promise { <pending> }, Promise { undefined }, Promise { <pending> } ]
// f3: resolved
// f4: resolved
// f5: resolved
// [ 'resolved', undefined, 'resolved' ]
結論
-
async
関数内での非同期処理はawait
しか使えない。-
async
とは下の2つ以上でも以下でもない。- 戻り値が
Promise
に入る - 中で
await
を使える
- 戻り値が
-
resolve
と違ってreturn
を非同期に待つわけではないので、やれることはnew Promise
の方が多い。 - なので、
await
を使わないなら使う意味ない。
-
- よって、チェーンの起点となるような
promise
は従来通りnew Promise
でつくるしかない。
ということで、 「await
使わないならasync
使わない」 が正しそう。(反論募集)
コメントをいただいて追記
f4
のthen
をawait
してreturn
すればいい(もっというとawait
なくてもいい)とのコメントをいただきました。確かに...!
しかしこうするともはやasync
の意味ないので、やはり上の結論が正しそう。
というか、Promise
にPromise
いれると中間のPromise
消えちゃうんですね。知らなかった...
let p1 = new Promise((r) => {
r('resolved');
});
let p2 = new Promise((r) => {
r(p1);
});
p2.then((p1) => {
console.log(p1)
});
// 実行結果
// 'resolved'