Share
Embed
JS 入門 async/await について
配信動画はこちら
https://www.youtube.com/watch?v=HFBZvK9_OUc&feature=youtu.be
もし良かったらムーザルちゃんねるのチャンネル登録お願いします!
https://www.youtube.com/channel/UCLPHXwLp90A5R69Eltxo-sg
Twitter でもプログラミングネタをつぶやいているのでフォローお待ちしております。
ムー
https://twitter.com/mu_book
zaru
https://twitter.com/zaru
ムーザルちゃんねる
November 05, 2020
Transcript
40 slides
-
話す人 現役のエンジニア二人 赤貝が好きな CTO と デザイン勉強中のエンジニア @mu_vpoe 最近の仕事は figma で画
面設計をつくることで す。英語の勉強してる。 ムー zaru @zaru CTO, Love 赤貝, JavaScript, Firebase, Web Components. Twitter フォロー お願いします! -
await で非同期の完了を待つ const res = await fetch('http://localhost:3000/'); JavaScript 非同期処理 完了を待つよ、という指示
非同期な処理の前に await と置くことで、同期的にコードを書く ことができて便利! という、とても簡単で便利な感じですね!! ??? -
同期と非同期処理の違い syncFuncA() syncFuncB() syncFuncC() 同期処理の流れ asyncFuncA() syncFuncB() syncFuncC() 非同期処理の流れ //
A が終わってから B // B が終わってから C // A を待たずに B // B が終わってから C 裏で処理をして いるイメージ 面倒くさ いジャン 非同期 嫌だ // A がいつ終わるかは // 分からない プログラマ的には、書いたコード順に実行して行って欲 しい(同期的)。非同期な処理が入ると、結果を受け 取って次の処理をするためのコードを書くのが面倒。 -
ブラウザはとにかく忙しい マウス移動 ボタンクリック 文字選択 フォーム入力 HTML レンダリ ング CSS スタ
イル描画 ユーザ操 作へ反応 ブラウザは HTML の表示に加えて、ユーザ操作に対する反応をし なくてはならず、絶え間なく忙しい。忙しいけど頑張っている。 サーバとの 通信 -
時間のかかる処理があると固まる めちゃく ちゃ重い 処理 時間のかかる処理があると、ブラウザは他の作業ができな くなる。ユーザの操作も受け付けることができない。ブラ ウザも頑張っているが、仕方がない…。 ・・・ ブラウザが固まって ユーザが操作不能に
❌ (*) なぜ他の処理ができないのかというとシングルスレッドだからという ことなのだけど、突っ込んだ話になるので別の機会に… -
通信処理() もし同期処理だったら リクエスト レスポンス この間、他の 操作や処理は 何もできない サーバ ❌ 通信処理()
通信は非同期 リクエスト レスポンス 通信中、他の 操作を受け付 ける サーバ おさらい -
通信処理() もし同期処理だったら リクエスト レスポンス この間、他の 操作や処理は 何もできない サーバ ❌ 通信処理()
通信は非同期 リクエスト レスポンス 通信中、他の 操作を受け付 ける サーバ つまり非 同期にし たいんだ ね -
通信処理() 通信中、他の 操作を受け付 ける 通信は非同期 リクエスト レスポンス サーバ const res
= 同期_通信処理('http://localhost:3000/'); // res 変数には通信処理の結果が入って来るので、すぐ使える JavaScript 通信処理() もし同期処理だったら リクエスト レスポンス この間、他の 操作や処理は 何もできない サーバ ❌ シンプルだ けど操作で きないのは 困る -
通信処理() もし同期処理だったら リクエスト レスポンス この間、他の 操作や処理は 何もできない サーバ ❌ 通信処理()
通信中、他の 操作を受け付 ける 通信は非同期 リクエスト レスポンス サーバ const res = 非同期_通信処理('http://localhost:3000/'); // res 変数には通信処理の結果は入ってこない!! JavaScript 困る 結果が使えないと意味ない…! -
- コールバック関数 - Promise ~ then - Promise ~ await
結果を受け取る3つの方法 Promise ...? -
コールバック関数で受け取る 昔から使われている XMLHttpRequest で結果を受け取るには load のイベ ントリスナーに関数を登録しておく。非同期処理の結果を受け取るには、こ のようなイベントやコールバック関数でやるのが昔の JS 流儀。
問題は、非同期処理の書き方が統一されていないことと、連続した非同期処 理をすると深いネスト構造になり破綻しやすいこと。 const xhr = new XMLHttpRequest(); xhr.addEventListener('load', (response) => { console.log(response.target.responseText); }); xhr.open('GET', 'http://localhost:3000/'); xhr.send(); XMLHttpRequest コールバック関数 -
波動拳 a.k.a Callback Hell fs.readdir(source, function (err, files) { if
(err) { console.log('Error finding files: ' + err) } else { files.forEach(function (filename, fileIndex) { console.log(filename) gm(source + filename).size(function (err, values) { if (err) { console.log('Error identifying file size: ' + err) } else { console.log(filename + ' : ' + values) aspect = (values.width / values.height) widths.forEach(function (width, widthIndex) { height = Math.round(width / aspect) console.log('resizing ' + filename + 'to ' + height + 'x' + height) this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) { if (err) console.log('Error writing file: ' + err) }) }.bind(this)) } }) }) } }) http://callbackhell.com/ -
コールバック関数 function callback(data) { console.log(data); } function something(id, callback) {
const result = `ID: ${id}`; callback(result) } something('zaru', callback); JS 初学者向け 通称、コールバック関数 特別な機能があるわけで はなく単なる関数定義 引数に関数自体を渡すことができる ここでは関数は実行されない点に注意 引数の関数に、処理した結果を渡し た上で実行する こうすることで特定の処理結果を任 意の関数に任せることができて便利 1 2 3 -
Promise は3つの状態を持つ Pending Fulfilled Rejected 最初は Pending (待機) で、非同期処理が正常に終わったら Fulfilled
(満足) へ、なんらかの理由で失敗した場合は Rejected (拒否) 状態に移る。 const promise = asyncFunc(); // Promise{<pending>} promise.then((response) => { // Promise{<fulfilled>} }).catch((error) => { // Promise{<rejected>} }); Promise の基本構文 正常に終わる場合は then へ 失敗した場合は catch へ -
Promise は then で受け取る fetch は XMLHttpRequest と同じように通信ができる。違う点は Promise というオブジェクトを使って非同期処理をする所。
Promise はコールバック関数とは違い、標準化され使い方が統一されてい る。then でつないでいくことで、連続した非同期処理をネストさせずに1直 線で書くことができるのがメリット。 fetch('http://localhost:3000/') .then((response) => { return response.text(); }) .then((response) => { return response; }); fetch then の中で受け取れる 次の非同期処理もつなげられる -
await はその場で待つ await を使うと then を使わずに、その場で待ってくれる。つまり、コード の書き方としては同期的に書けるが、実際の処理は非同期で行うので、他の 処理を止めることはない、いいとこ取りな機能。 const response
= await fetch('http://localhost:3000/'); const text = await response.text(); console.log(text); fetch スッキリ -
await 拒否の受け取り方 const response = await fetch('http://localhost/').catch((error) => { console.log(error);
}); try { const response = await fetch('http://localhost/') } catch (error) { console.log(error); } ドットチェイン catch で 受け取ることができる try の catch でも受け取れる どちらで書いた方がいいかはケースバイケースだが、ドッ トチェインの catch で受け取った方がシンプルな書き方 になることが多い。 -
async は非同期関数を作る async function asyncFunc() { return 1; } function
asyncPromise(){ return new Promise((resolve) => resolve(1)) } asyncPromise().then((res) => res ); asyncFunc().then((res) => res ); Promise と async 関数の前に置くことで自動で Promise を返す非同期関数になる 手動で Promise オブジェクトを 作って返す関数と基本的には同じ 呼び出し方も then や await など で同じように使える 非同期処理を使うだけなら async は Promise を手動で作るのと 同じなんだ〜くらいの認識で OK -
await は async 内じゃないと使えない ❌ 実はこれはエラーになる const response = await
fetch('http://localhost/'); ✅ async 関数の中じゃないと await は使えない async function fetchUrl() { const response = await fetch('http://localhost/'); } (async () => { const response = await fetch('http://localhost/'); })(); async 2020.11 現在では await はトップレベルでは使えず async で非同期宣言を した関数の中でしか使えない。将来的には使えるようになる予定(NodeJS は v14.8 以降使える) https://github.com/tc39/proposal-top-level-await -
イベントループ タスク タスク タスク タスク タスク ユーザの操作やスクリプトの 実行などタスクを積んでいく 暇になったら古いタスクから 拾って順次処理をしていく
JavaScript の処理は、イベントループと言われる構造で実行し ている。処理したいタスクをキューに積んでいき、順次処理をし ていくイメージ。 -
どの順序で出力される? console.log('start'); setTimeout(() => console.log('setTimeout'), 0); (async () => {
await 0; console.log('async') })(); function promiseFunc() { return new Promise((resolve) => resolve()) } promiseFunc().then(() => console.log('promise')); Promise.resolve().then(() => console.log('resolve')); console.log('end'); JavaScript -
どの順序で出力される? console.log('start'); setTimeout(() => console.log('setTimeout'), 0); (async () => {
await 0; console.log('async') })(); function promiseFunc() { return new Promise((resolve) => resolve()) } promiseFunc().then(() => console.log('promise')); Promise.resolve().then(() => console.log('resolve')); console.log('end'); JavaScript start end async promise resolve setTimeout 答え -
タスク タスク タスク タスク タスク タスク タスク タスク macrotask microtask
レンダリング requestAnimationFrame 描画系の処理 Promise setTimeout I/O Network Mouse Keyboard 1 macrotask から1個タ スクを受け取り処理をす る 3まで完了したら次のタ スクを受け取り処理をす る 2 microtask から全て のタスクを受け取り処 理をする 3 必要があれば描画に関連する処理を行う 無限ループ -
ありがとうございました! 次回は... 未定! 質問感想など呟いていただけると嬉しいです! - ハッシュタグ #mu_zaru - ツイッター情報 @mu_vpoe
, @zaru チャンネル登録 Good ボタン お願いします! ムーザルちゃんねる