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'