Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

JavaScript辞典

async / await対応: ES2017(ECMAScript 2017)

非同期処理を同期処理のように直感的に記述するための構文です。『async』で非同期関数を宣言し、『await』でPromiseの完了を待ちます。

構文
// async関数を宣言します。戻り値は自動的にPromiseになります。
async function 関数名() {
	// awaitでPromiseの完了を待ちます。
	var result = await Promise;
}

// アロー関数での書き方
var 関数名 = async function() {
	var result = await Promise;
};
キーワード一覧
キーワード概要
async関数の前に付けることで、その関数を非同期関数にします。非同期関数の戻り値は常にPromiseになります。
awaitPromiseの完了を待ち、結果の値を取り出します。async関数の中でのみ使用できます。
サンプルコード
// テスト用の非同期関数
function wait(ms) {
	return new Promise(function(resolve) {
		setTimeout(function() {
			resolve("" + ms + "ミリ秒待ちました");
		}, ms);
	});
}

// async/awaitの基本的な使い方
async function main() {
	console.log("開始");
	var result = await wait(2000); // 2秒間待ちます。
	console.log(result); // 『2000ミリ秒待ちました』と出力されます。
	console.log("完了");
}
main();

// then()を使った書き方との比較
// then()版: ネストが深くなりがちです。
wait(1000).then(function(msg1) {
	console.log(msg1);
	return wait(1000);
}).then(function(msg2) {
	console.log(msg2);
});

// async/await版: 上から下に読める直線的なコードになります。
async function sequential() {
	var msg1 = await wait(1000);
	console.log(msg1); // 『1000ミリ秒待ちました』と出力されます。
	var msg2 = await wait(1000);
	console.log(msg2); // さらに1秒後に『1000ミリ秒待ちました』と出力されます。
}
sequential();

// try...catchでエラーを処理します。
async function fetchUserData() {
	try {
		var response = await fetch("https://api.example.com/user");
		var data = await response.json();
		console.log(data.name);
	} catch (error) {
		console.log("データの取得に失敗しました: " + error.message);
	} finally {
		console.log("通信処理が完了しました");
	}
}
fetchUserData();

// 複数の非同期処理を並列実行する方法
async function loadAll() {
	// Promise.all()とawaitを組み合わせて、並列実行の完了を待ちます。
	var results = await Promise.all([
		fetch("https://api.example.com/users"),
		fetch("https://api.example.com/posts")
	]);
	console.log("すべてのデータを取得しました");
}
loadAll();
実行結果
"開始"
"2000ミリ秒待ちました"   // 2秒後に出力されます
"完了"

"1000ミリ秒待ちました"   // 1秒後に出力されます
"1000ミリ秒待ちました"   // さらに1秒後に出力されます

"通信処理が完了しました" // finally は常に実行されます
awaitの注意点

『await』はasync関数の中でしか使えません。通常の関数やグローバルスコープで使用するとエラーになります。

// エラーになる書き方
function normal() {
	var result = await wait(1000); // SyntaxError: async関数の外では使えません。
}

// async関数の中で使う正しい書き方
async function correct() {
	var result = await wait(1000); // 正常に動作します。
	console.log(result);
}
correct();

また、awaitを順番に書くと処理が直列に実行されるため、互いに依存しない処理は『Promise.all()』で並列実行した方が効率的です。

// 直列実行: 合計3秒かかります。
async function slow() {
	var a = await wait(1000); // 1秒待ちます。
	var b = await wait(2000); // さらに2秒待ちます。
	console.log(a, b);
}

// 並列実行: 最も遅い2秒で完了します。
async function fast() {
	var results = await Promise.all([wait(1000), wait(2000)]);
	console.log(results[0], results[1]);
}
概要

『async / await』はES2017で追加された、Promiseをより簡潔に扱うための構文です。『Promise』の『then()』チェーンでは処理が複雑になるほどコードが読みにくくなりますが、『async / await』を使うと通常の同期処理と同じ見た目で非同期処理を記述できます。

async関数は必ずPromiseを返します。関数内で値を『return』すると、それは自動的に『Promise.resolve()』で包まれます。エラーが発生した場合は『Promise.reject()』で包まれ、呼び出し元で『catch()』や『try...catch』で処理できます。

現代のJavaScript開発では、非同期処理のほとんどが『async / await』で記述されています。サーバーとの通信、データベースへの問い合わせ、ファイルの読み書きなど、完了を待つ必要がある処理を直感的に書けるため、初心者にとっても理解しやすい構文です。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。