これは何?
async/awaitとPromiseの関係を今更だけど自分なりに理解したときのメモです。
説明
Promise
非同期処理の書き方を定めたJavaScriptとしてのルール。
- うれしい点
- 非同期処理の書き方が統一され可読性が向上
- Callbackのネストを浅くすることができる
詳細は「今更だけどPromise入門」が分かりやすい。
async/await
Promiseの弱点である、多い回数のループの処理をより簡単に書くことができるようにするJavaScriptとしてのルール。
Promiseを先に理解する必要があるが覚えるととても便利。
-
うれしい点
-
あたかも同期処理のような書き方ができる為、コード量の減少、可読性の向上が期待できる
-
覚書
-
awaitはPromiseの処理完了を待つことができるので、記述的に非同期処理をあたかも同期処理と同じように記述できる
-
awaitを関数の中に入れる場合には、その関数をasyncとして宣言する必要がある
-
Promiseと混ぜて書くことももちろん可能
詳細は「async/await 入門(JavaScript)」が分かりやすい。
XHRを書いてみる
fetch()がある現代ではその意味はゼロだけど理解するために書いてみた。
コード
実行と同時に青い丸を表示します。非同期にurl
で指定したページ(例では「http://localhost/hoge.html
」)を取得後、delay
で指定された時間(例では「3秒」)だけ待ち、取得した内容を画面に表示するスクリプトです。
<html>
<head>
<title>XHRとasync/await</title>
<style>
.blue-circle {
width: 100px;
height: 100px;
background-color:#536DFE;
border-radius:50%;
}
</style>
</head>
<body>
<script>
function asyncxhr(url) {
return new Promise( (resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.send();
xhr.onreadystatechange = function() {
if(xhr.status === 200 && xhr.readyState === 4) {
setTimeout( () => {
resolve(xhr.responseText);
}, 3000);
/* http status code: https://httpstatuses.com/ */
} else if(xhr.status >= 307 && xhr.readyState === 4) {
reject(new Error(xhr.statusText));
}
}
xhr.onerror = function() {
reject(new Error(xhr.statusText));
}
});
}
// [ここから] 別の書き方
async function exec00(url, msec) {
try {
const content = await asyncxhr(url, msec);
console.log('[SUCCESS] ', content);
let pre = document.createElement('pre');
pre.innerText = content;
document.body.append(pre);
} catch(error) {
console.log('[ERROR] ', error);
}
}
const url = 'http://localhost/hoge.html';
const delay = 3000;
exec00(url, delay);
// [ここまで] 別の書き方
let div = document.createElement('div');
div.classList.add('blue-circle');
document.body.append(div);
</script>
</body>
</html>
ちなみに別の書き方
の部分は以下のように即時関数で書くことも可能です。
(async function() {
try {
const url = 'http://localhost/~kawai/tmp/aaa/index.html';
const delay = 3000;
const content = await asyncxhr(url, delay);
console.log('[SUCCESS] ', content);
let pre = document.createElement('pre');
pre.innerText = content;
document.body.append(pre);
} catch(error) {
console.log('[ERROR] ', error);
}
}());
実行画面
最低3秒間の時間を待って、取得したページの内容を表示していることが分かる。

まとめ
Promiseの理解がasync/awaitを使う条件ですが覚えるとコード量が減る上、可読性も上げることができるので全体的にスピードアップが期待できるのではないでしょうか?