LANG SELRCT

コードを書く場所

2019年2月24日日曜日

JavaScriptの非同期処理の理解を試みた備忘録


AWS Lambda で Function を作る際、デフォルトで入っているコードの中に 「async」 というのがありました。
exports.handler = async (event) => {
    // TODO implement
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

これまで使う機会がなくて使ってきませんでしたが、今回これを使う際にいくつかぶつかった非同期処理の理解に立ちはだかる壁について書きます。


asyncがどんなものかを知ろうとして調べてみると、、

asyncの仕組みを理解しようと思ったら
Promiseの仕組みの理解が必要でした。

Promiseの仕組みを理解しようと思ったら
コールバック関数の仕組みの理解が必要でした。

コールバック関数の仕組みを理解しようとしたら
非同期処理の仕組みの理解が必要でした。

非同期処理の仕組みを理解しようとしたら
同期処理の仕組みの理解が必要でした。


初見では意味不明な言葉ばかりなので、このページでの定義を個人的に理解した言葉で表現し直してみます。

「処理」
  • コードが結果を返すまでの計算作業

「同期処理」(sync)
  • 処理をひとつずつ順番に実行して結果を渡していく
  • その間は他の処理を同時に実行しない

「非同期処理」(async)
  • 同時に複数の処理を実行する
  • 時間のかかる処理の結果が返ってきてから次の処理を実行するには工夫が必要
    • その工夫として「コールバック関数」「Promise」「async/await」がある
  • ボタンを押したら実行する.onclick等は非同期処理
    • そのコードが書かれていてもボタンが押されるまで実行されない
  • ググっていろいろなページを見ていると、「非同期処理を実装する」と表現されているものの、「非同期処理を同期的に実装する」という意味で使われていたりする
    • JavaScript自体は非同期処理
    • 処理の結果を待たず次々と実行されるので時間がかかる処理があると渡したい値が渡らない
    • そこで、結果が返ってきてから値を渡すようにそこだけ同期処理にしてやる
    • それを「コールバック関数」「Promise」「async/await」で実現する

「コールバック関数」
  • 非同期処理で処理の実行タイミングをコントロールしたいときに使える
  • 引数として他の関数に渡す関数
  • コールバック関数が重なると可読性が良くないためPromiseが生まれた

「Promise」とは
  • 非同期処理の結果を待ってから次の処理を実行したいときに使える
    • 時間のかかる処理は先にその処理結果を返すための入れ物だけを返しておいて、処理が終わって結果が返ってきたらその入れ物に結果を渡してやる
  • Callback関数よりも簡潔に処理の実行タイミングをコントロールできる
  • Promise の状態
    • pending: 初期状態
    • fulfilled(resolve): 処理が成功した
    • rejected(reject): 処理が失敗した
    • 入れ物を作ったときはpending状態で「まだ結果が返ってきていないからちょっと待っててね」状態、結果が返ってきたらfulfilled状態になって「お、成功して結果が返ってきたよ、はいこれ」状態、エラーが返ってきたらrejected状態になって「おや、処理がうまく行かなかったみたいだよ、こんなの返ってきたよ」状態
  • promise.then(funcA)
    • promiseの処理が成功したらfuncAを実行する
  • promise.catch(errorFunc)
    • promiseの処理が失敗したらerrorFuncを実行する
  • Promiseの作り方
    1. var promise = new Promise(function (resolve, reject){})
    2. var promise = Promise.resolve(myFunc())

「async/await」とは
  • Promiseの処理を簡素化して書ける


関連記事



参考

Promiseを使う