止まらない画面:Fetchとasync_await
7分22秒 | フロントエンドASYNC
基本情報技術者試験の頻出テーマを解説した動画コンテンツです。
トランスクリプト(字幕テキスト)
いや、最近ですね、データを送るプログラムを書いたんですけど、ボタンをポチッと押した瞬間、画面がこうピタッと数秒間固まっちゃうんですよね。 これ、正直使いにくいじゃないですか。あー、それウェブ開発あるあるですよね。 せっかくいい感じの機能を作ったのに、いざボタンを押してみたらUIが全く応答しなくなる。あー。 ユーザーからしたら結構なストレスですけど、これにはちゃんとした理由があるんですよ。 さて、この問題の核心に迫っていきましょう。これって、プログラムの処理の仕方に原因があるんです。 具体的に言うと、『同期処理』と『非同期処理』っていう2つのやり方の違いですね。 今回の画面フリーズは、まさにこの同期処理ってやつが引き起こしてるんです。 これ例えるならレストランがすごく分かりやすいんですよ。同期処理っていうのは注文した後、 料理が出てくるまでずっとレジの前で仁王立ちしてるイメージです。もう、他のことは何もできない。 でも、非同期処理だと、あのー、呼び出しベルを渡されるじゃないですか。 あれを受け取って、席でスマホでも見ながら待てるわけです。つまり、待ち時間を有効活用できるってことなんですよね。 まさにこのスライドが、その違いをバッチリ示してくれてますよね。同期処理だとブラウザは、 通信っていう1つのタスクにつきっきりになっちゃって、他のことが全部ストップしてしまう。 でも非同期処理なら、ベルが鳴るのを待ってる間に他の作業もちゃんと進められる。 だからアプリがサクサク軽快に動くっていうわけなんです。 じゃあどうすればコードにその便利な呼び出しベルシステムを導入できるのか。そこで登場するのが、 asyncとawait。もうこれまるで魔法の呪文みたいなキーワードのペアなんです。 まずはasyncから。これを関数の前にポンとつけるだけ。たったこれだけで、 オッケー、この関数の中ではちょっと時間がかかる処理、つまりレストランでいう料理を待つ、 みたいなことをやりますよ、っていうJavaScriptへの宣言になるんです。これがおまじないの第一歩ですね。 そして、asyncをつけた関数の中だけで使える特別な言葉がこのawaitです。 これは、ここで処理の結果が返ってくるまでちょっと待っててねっていう指示。 でもここがすごい大事なポイントなんですけど、ブラウザ全体の動きは止めずに、その処理だけをスマートに待ってくれるんですよ。 ということはですよ、await fetchって書けば、通信が終わるのをちゃんと待ってから次の処理に進んでくれる。 しかも画面は固まらない、ってことですね。まさにその通り。これがないと、 データが届くより先に画面を更新しようとしちゃって、エラーになったりするので、めちゃくちゃ重要なんです。 さて、そのasync awaitと最高のコンビを組むのがFetch APIです。 これはネットワーク通信をするためのツールで、今のブラウザにはもう標準で入っている、すごくパワフルなやつなんですよ。 fetchですか。うーん。Axiosっていうライブラリの名前もよく聞きますけど、あれとはどう違うんですかね。 あ、いい質問ですね。Axiosもすごく人気で便利なライブラリです。ただfetchの最大の強みは、 ブラウザに元から入ってるので、何も追加でインストールしなくていいってこと。このスライドでポストリクエストの書き方を比べてますけど、 パッと見は結構似てますよね。 で、この表が2つの違いをすごく分かりやすくまとめてくれてます。fetchは標準装備で軽い。 でも、データの形式変換とか一部のエラー対応は自分で書く必要があります。一方でAxiosは、その辺を自動でやってくれる便利機能がてんこ盛り。 どっちがいい、悪いじゃなくて、プロジェクトの状況に合わせて使い分けるのが賢い選択ですね。 なるほど、基本はだいぶ分かってきました。でも実際の開発現場ってもっと色々な『もしも』が起こりますよね。 おっしゃる通りです。リクエストを送って終わりなんてことはまずないですからね。 ここからはもっと実戦でどう対応していくか見ていきましょう。例えばよくあるのがリクエストの失敗。 こういう時にあるのがtry/catchブロックです。失敗しそうなawaitの呼び出しをまるっとtryで囲っておく。 そうすれば、もしネットワークエラーとかが起きても、catchブロックでしっかりそれを捕まえて、 ユーザーに『エラーが出ました』ってメッセージを見せたりできるわけです。 ただですね、fetchには1つすっごく大事な注意点があって、これ結構はまりがちなんですけど、 fetchって通信そのものが失敗しない限り、例えばサーバーから404見つかりません、 みたいなエラーが返ってきても、それをプログラム上のエラーだとは見なしてくれないんですよ。 なのでレスポンスを受け取ったら、必ずこのresponse.okっていうプロパティがtrueかどうか、自分でチェックしないといけないんです。 これ本当に忘れがちな罠なんで、ぜひぜひ覚えといてください。なるほど。 じゃあ例えばユーザーの情報とその人の投稿一覧みたいに、複数のデータをいっぺんに取りたい時ってどうすればいいでしょう。 そういう時に頼りになるのがPromise.allです。これは複数のリクエストを配列にして渡してあげると、 その全部が終わるまで待ってくれるっていう優れもの。これを使えば、関連するデータを効率よくまとめてゲットできます。 ただ1つ注意点があって、どれか1つでも失敗すると全部が失敗扱いになっちゃうので、そこは気をつけてくださいね。 あともう1つ、これも本当によくありそうなんですけど、リクエストを送った途中で、 ユーザーが待ちきれずに別のページに移動しちゃったらどうなっちゃうんですか。 あー、それも超典型的な問題ですね。コンポーネントはもう画面から消えちゃったのに通信だけは続いてて、 終わった後にもう存在しない場所のデータを更新しようとしてエラーになる。メモリーリークの原因にもなったりします。 その問題を解決してくれるのが、このAbortController。これを使うと、 通信を途中でキャンセルするための『中止信号』みたいなものを作れるんです。 fetchリクエストをする時にその信号を一緒に渡しておけば、いつでもabortっていう命令一つで通信をピタッと中断できるんですよ。 例えばReactのuseEffectフックを使ってるなら、クリーンアップ関数、 つまりお片付けの処理の中でこのabortを呼び出すように設定しておくんです。 こうすればコンポーネントが画面から消えるタイミングで、いらなくなった通信も一緒にキャンセルされる。 これでアプリケーションがもっと安全で効率的になるわけです。なるほど。いや、これで僕の開発者ツールキットも、 かなりパワーアップした感じがしますね。ええ。 では最後に、今日手に入れたこの強力なツールたちを、もう一度整理しておきましょう。まず、読みやすい非同期コードを書くためのasync await。 それから、ブラウザ標準の通信ツールFetch API。エラーをしっかり捕まえるtry/catch。 複数のリクエストを華麗にさばくPromise.all。そして不要になったリクエストを中断するためのAbortController。 これがあなたの非同期処理の基本セットになります。これらのツールをしっかり使いこなせば、 ただ画面が固まるのを防ぐだけじゃない、ユーザーにとってもっとずっと快適で質の高いアプリケーションが作れるようになります。 さあ、この止まらないUIという武器を手に入れた今、あなたは次に何を作り出しますか?
このコンテンツは Web society で視聴・学習できます。