概要
前回の続きです。
今回はPromiseを同期処理っぽく書ける「async/await」編です。
async/awaitの背景
ES6で実装されたPromiseの誕生により、
非同期処理がすごく簡単に書ける様になりました。
ただ、書き方はどうしても特殊で、
普段のプログラムでは見ない形です。
(モダンJSに慣れている人なら違和感はないと思いますが。)
そこで、Promiseをよりシンプルに且つ可読性が高まる様にとラッピングされたのが、
「 async/await 」の記法です。
何か特別な新しい考え方という訳ではなくて、
あくまでも、非同期をより読みやすくする新文法ぐらいの認識で問題ないと思います。
async/awaitはES7(ES2016)で実装されています。
async/awaitの使い方
async
asyncは関数宣言の前に記載します。
asyncが記載された関数は、必ずPromiseを返す様になります。
const func = async () => {
return 23;
};
上のコードをasyncなしで書くと以下になります。
const func = () => {
return new Promise((resolve) => {
resolve(23);
});
};
await
awaitはasync関数内でのみ使える文法です。
awaitはPromise.then(result => result))
のラッパーで、
thenチェーンを使わずに、同期処理の様な記述で非同期処理を記載できます。
それにより可読性がグンと上がります。
(トップレベルでのawaitの使用は不可能)
const func = async () => {
return 23;
};
const awaitFunc = async () => {
// resolveが23のPromiseオブジェクトが出力される
console.log(func());
// func().then(result => result)で23が出力される
console.log(await func());
};
awaitFunc();
awaitで同期っぽく書いている例が以下になります。
(awaitの付与でPromiseの完了を待っている状態)
const sleep = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(23);
}, 3000);
});
};
const awaitFunc = async () => {
await sleep();
// awaitでPromise終了を待ってから、logが出力される。
console.log('done!!!');
};
awaitFunc();
awaitはPromiseの結果を返すので、以下の様な書き方もできます。
const sleep = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(23);
}, 3000);
});
};
const awaitFunc = async () => {
const result = await sleep();
// 23が出力される。
console.log(result);
};
awaitFunc();
ちなみに、awaitを使わずに書いた場合こうなります。
const sleep = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(23);
}, 3000);
});
};
const awaitFunc = async () => {
sleep()
.then((result) => {
console.log(result);
});
};
awaitFunc();
これだけではいまいち良さはわかりませんが、
コールバック地獄や、Promiseのthen地獄、Promise.allでの並列処理などをたくさん書いている人は、
恩恵がイメージ出来るのではないかと思います。
終わり
async/awaitを使う事で、同期処理っぽく非同期処理が書けるイメージができたかと思います。
前回の冒頭で書いた通りで、
モダンJSでは非同期の取り扱いが非常に重要です。
async/awaitでしっかり可読性をあげれば、
「あれ?undfinedになってる...」のあるあるパターンともおさらばかと思います。
ES7での実装ですが、今後のスタンダードな書き方になると思うので、
積極的に利用していこうと思います。