2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

async / awaitへの誤解と理解:async==new Promiseではない

Last updated at Posted at 2020-05-07

async/awaitについて勝手に誤解していたこと。

Promiseまわりの記述を置き換えるわけじゃない

なんか勝手にそう思ってたので飲み込めてなかった。

asyncreturn new Promiseとおなじこと ...正しいようで違う

以下のコードでは「同じ」ように振舞う。

let f1 = () => {
    return new Promise((resolve) => {
        return 'resolved';
    });
}

let f2 = async () => {
    return 'resolved';
}

// f1() == Promise { 'resolved' }
// f2() == Promise { 'resolved' }

が、それは非同期処理をしていないから。現実にはPromiseを使うなら必ず非同期処理をするから、以下のポイントが重要になる。

async中のreturnresolveと同じように使える ...間違い

下のコードで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使わない」 が正しそう。(反論募集)

コメントをいただいて追記

f4thenawaitしてreturnすればいい(もっというとawaitなくてもいい)とのコメントをいただきました。確かに...!

しかしこうするともはやasyncの意味ないので、やはり上の結論が正しそう。

というか、PromisePromiseいれると中間のPromise消えちゃうんですね。知らなかった...

let p1 = new Promise((r) => {
    r('resolved');
});

let p2 = new Promise((r) => {
    r(p1);
});

p2.then((p1) => {
    console.log(p1)
});

// 実行結果
// 'resolved'
2
2
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?