async を関数定義に付けると、その関数は常に Promise を返すようになります。await と組み合わせることで、非同期処理を同期的に書いているかのように記述でき、可読性と保守性が大幅に向上します。
基本的なVue 3コンポーネントでの使用例
<template>
<div>
<p v-if="isLoading">データ取得中...</p>
<div v-else>
<pre>{{ fetchedContent }}</pre>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const fetchedContent = ref('');
const isLoading = ref(true);
const retrieveRemoteData = async () => {
try {
const apiResponse = await fetch('https://jsonplaceholder.typicode.com/posts/1');
if (!apiResponse.ok) throw new Error('HTTPステータスエラー');
const payload = await apiResponse.json();
fetchedContent.value = JSON.stringify(payload, null, 2);
} catch (err) {
fetchedContent.value = `エラー: ${err.message}`;
} finally {
isLoading.value = false;
}
};
onMounted(() => {
retrieveRemoteData();
});
</script>
コードのポイント解説
- async関数の宣言:
retrieveRemoteDataはasyncで定義され、内部でawaitを使用可能。 - awaitによる待機:ネットワークリクエストやJSON変換といった非同期処理を順番に待機し、直感的なフローで記述。
- エラーハンドリング:
try/catch/finallyで例外を捕捉し、UI状態を安全に更新。 - マウント時の実行:
onMountedフック内で非同期関数を呼び出し、コンポーネント表示時に自動実行。
実用的な応用例:リストデータの取得
<template>
<div>
<ul v-if="!isLoading">
<li v-for="post in postList" :key="post.id">
{{ post.title }}
</li>
</ul>
<p v-else>投稿一覧を読み込み中...</p>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const postList = ref([]);
const isLoading = ref(true);
const loadPosts = async () => {
try {
const res = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=5');
if (!res.ok) throw new Error('APIリクエスト失敗');
postList.value = await res.json();
} catch (error) {
console.warn('投稿の取得に失敗しました:', error);
postList.value = [];
} finally {
isLoading.value = false;
}
};
onMounted(loadPosts);
</script>
この例では、APIから投稿リストを取得し、v-for で動的に描画。非同期処理が完了するまでローディング表示を行い、UXを考慮した設計になっています。