search
LoginSignup
7

posted at

updated at

Promiseとasyncとawaitをできるだけ短く解説してみる

Promise…そうそれは
簡単そうに思えてややこしく、困難そうに思えて容易い、そんなラララ (by Mr.Chldren)

前回の記事 JavaScriptをもうちょっと理解する54のトピック で軽く触れたPromiseについてです。

次回、Promiseについて本気出して考えてみた記事を書く予定ですが、前哨戦としてなるべく短くかみ砕いた記事を書きます。asyncとawaitに触れるにはPromiseを避けられないので、Promiseはわずかばかり丁寧に。

Promise

Promiseの発生

Promiseは自分で作るか、関数の戻り値で発生します。

  • Promiseを返す主な関数は fetch とか fs.readFile あたりだよ
  • new Promise(関数) で生成することもできるよ

Promiseがもつ3つの状態

Promise の状態は3つ。処理中の pending 、成功したときの fulfilled 、失敗の rejected のいずれかです。

  • 例えばfetch関数なら実行した瞬間は pending 。完了すると fulfilledrejected になるよ
  • 状態が fullfilledとrejectedのPromiseは何らかの を持っているよ
  • rejectedの持つ値は基本的には Error だよ

続きの処理は .then か .catch で書ける

状態が fulfilledrejected なら続きの処理を実行できます。

  • fulfilledなら プロミス.then(処理) で。 処理 の第1引数には が入っているよ
  • rejectedなら プロミス.catch(処理) で。 処理 の第1引数には 値(基本はError) が入っているよ

.then や .catch の戻り値も Promise

.thenや.catchの戻り値はPromiseです。Promiseということは、さらに.thenで続けられます。

  • Promiseをreturnすれば、returnしたPromiseがそのまま 返るよ(例: fetchをreturnするなど)
  • Promise以外の値をreturnすれば、状態がfullfilledで、returnした値を持つPromise が返るよ

async

通常の(普通の)functionで値をreturnするとその値が返りますが、 async function で値をreturnすると、 状態がfullfilledで、returnした値を持つPromise が返ります。

  • functionの中に await を書きたい時に async function にするよ
  • functionの前(左)に async を付けるだけだよ

await

Promiseでは、.thenで続きの処理を実行できると書きましたが、それをもっとシンプルに書けます。

  • 状態がfulfilledなPromiseの左に await をつけると、Promiseそのものではなく Promiseが持っている値 が返るよ
    • 状態がpendingの場合は、 fulfilledかrejectedになるまで待つ
    • rejectedになった場合はエラーが発生するので、普通のtry catchでエラー処理できるよ
  • await は async functionの中でだけ書くことができるよ

※ Top-Level-Awaitのことはこの記事では考えません

最後に全体のイメージをコメントで解説

// fetchのところでawaitを使いたいのでfunctionの左にasyncをつける
async function fetchArticle() {
    try {
        // awaitでfetchの完了を待つ&値の取り出し
        const response = await fetch('Articleを取得するAPIのURL');
    
        // .json()の戻りもPromiseだが、awaitにより値として返る
        const articleJson = await response.json();

        // Promiseでない値を返すが、async functionなのでこの値を持ったPromiseで返る
        return articleJson;

    } catch (error) {
        // もしどこかでawaitの右側がrejectedになったらここに来る
        console.error(error);
    }
}

/**
 * 使う側の例その1
 * asyncなfunction(fetchArticle)がPromiseを返すので、状態がfulfilledになり次第.thenで処理する
 */
fetchArticle().then(articleJson => 処理);

/**
 * 使う側の例その2
 * asyncなfunctionの中から呼び出してawaitで処理
 */
async function hoge() {
    // asyncなfunction(fetchArticle)が返すPromiseを、awaitで待つ&値の取り出し
    const articleJson = await fetchArticle();

    // 何らかの処理~~(略)
}

お気づきでしょうか。使う側の例その2、これを呼び出す側は async+await.then のどちらかで呼び出すということに。

無限ループのようですが、非同期処理であるPromiseは結局どこかで .then(=終わり次第) で処理しなければならないのです。

まとめ

なるべく短く解説してみましたが、どうでしょう、ちゃんと短く書けたでしょうか?(そこ)

Promise、どちらかというと奥が深いようで意外にシンプルなものだと思うんですが、非同期処理に慣れないとややこしく感じると思います。この記事が少しでも何かのヒントになれば幸いです。

次回、「Promiseについて本気だして考えてみた」でお会いしましょう~(予定)

おまけ

よければF12を押して開発者ツールを開いて、Consoleで下のコードなどを試してみてください。
asyncの有無で何が変わるか確認できますよ!

function onlyFunc() {
    return 1;
}

async function asyncFunc() {
    return 1;
}

console.log('onlyFunc', onlyFunc());
console.log('asyncFunc', asyncFunc());

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
What you can do with signing up
7