0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

わかったようでわからない非同期処理の完全理解②:Axiosを使うとどうなる?

0
Posted at

前回は、async / await を使って、データが届くまで待ってから画面へ表示する流れを整理しました。

今回はAxiosを使って、ソードの情報を取りに行きます。成功したときと、失敗したときで何をするかを、.then().catch() で分けて書いてみます。

まだ途中段階なので、勘違いなどあれば教えていただけるとうれしいです。

今日やったこと

Axiosでデータを取りに行き、成功と失敗で画面の表示を変えるコードを書いてみました。

Axiosは、ファイルやAPIへ「データをください」と頼むための道具です。Axiosは、返事が届く前にPromiseを返します。 axios-http

今回は、ゲームの世界で鍛冶屋へソードを取りに行く場面に置き換えて考えます。

  • 鍛冶屋へソードを取りに行く
  • 受け取れたら、ソード名を表示する
  • 受け取れなかったら、失敗したことを表示する
キャラクター 「鍛冶屋さんに行ったら、ソードを受け取れるときと、まだ受け取れないときがあるんだね」

まずは、AxiosをVueプロジェクトへ追加します。

# Axiosをプロジェクトで使えるように追加する
npm install axios

今回も、public フォルダに sword.json を置く想定です。

{
  "name": "Iron Sword"
}

このファイルは、/sword.json として読み込みます。

つまずいたところ

ソードを受け取れたときと、受け取れなかったときで、することが違う点を整理しました。

.then() は受け取れた後

.then() の中には、ソードを受け取れた後にすることを書きます。

<script setup>
// Axiosを使えるように読み込む
import axios from 'axios'

// ソード情報を取りに行く
axios.get('/sword.json')
  .then((response) => {
    // ソードを受け取れた後に、この中が動く

    // Axiosで受け取ったデータはresponse.dataに入っている
    console.log(response.data.name)
  })
</script>

axios.get('/sword.json') は、ソード情報を取りに行く処理です。

ソード情報が届くと、.then() の中が動きます。Axiosでは、受け取ったデータは response.data に入っています。 axios-http

ゲームで考えると、.then() は「完成したソードを受け取れたら、その名前を装備欄に表示する場所」に近そうです。

.catch() は受け取れなかった後

.catch() の中には、ソードを受け取れなかったときにすることを書きます。

<script setup>
import axios from 'axios'

// ソード情報を取りに行く
axios.get('/sword.json')
  .then((response) => {
    // 受け取れたときにすること
    console.log(response.data.name)
  })
  .catch(() => {
    // 受け取れなかったときにすること
    console.log('ソード情報を受け取れませんでした')
  })
</script>

.catch() は、Promiseが失敗したときに動かす処理を書くために使います。 developer.mozilla

キャラクター 「受け取れたら `.then()`、受け取れなかったら `.catch()`。行き先が2つに分かれていると見やすいね」

今の自分には、.then().catch() は次のように見えています。

  • .then():うまくいった後にすること
  • .catch():うまくいかなかった後にすること

今の理解(メモ)

Vue 3の画面では、成功ならソード名、失敗なら失敗した文章を表示する形にしてみました。

<script setup>
// Axiosを使えるように読み込む
import axios from 'axios'

// onMountedは画面が表示された後に処理を始めるために使う
// refは画面に表示する値を覚えておくために使う
import { onMounted, ref } from 'vue'

// 成功したときに、ソード情報を入れる箱
const sword = ref(null)

// 失敗したときに、画面へ出す文章を入れる箱
const errorMessage = ref('')

// ソード情報を取りに行く関数
const loadSword = () => {
  // Axiosでsword.jsonを取りに行く
  axios.get('/sword.json')
    .then((response) => {
      // 成功したとき、受け取ったソード情報を箱へ入れる
      sword.value = response.data
    })
    .catch(() => {
      // 失敗したとき、画面に出す文章を箱へ入れる
      errorMessage.value = 'ソード情報を受け取れませんでした'
    })
}

// 画面が表示された後に、ソード情報を取りに行く
onMounted(loadSword)
</script>

<template>
  <main>
    <!-- ソードを受け取れたときに表示する -->
    <section v-if="sword">
      <h1>完成したソード</h1>
      <p>{{ sword.name }}</p>
    </section>

    <!-- 受け取れなかったときに表示する -->
    <p v-else-if="errorMessage">{{ errorMessage }}</p>

    <!-- まだ結果が分からない間に表示する -->
    <p v-else>ソードを探しています...</p>
  </main>
</template>

画面は、次の3つの状態に分かれます。

状態 画面に出るもの
まだ返事を待っている ソードを探しています...
ソードを受け取れた 完成したソードIron Sword
受け取れなかった ソード情報を受け取れませんでした

ゲームで考えると、装備欄は最初から完成品を出すのではなく、「探し中」「完成品あり」「受け取れなかった」の3つを表示し分けるような形です。

ref に入れた値が変わると、Vueが画面表示も更新します。Vue.js公式ドキュメント また、onMounted() は画面が表示された後に処理を始めるために使えます。 ja.vuejs

async / await でも書ける

Axiosを使うと、async / await が使えなくなるわけではありません。

前回と同じように、async / awaittry / catch で書くこともできます。

<script setup>
import axios from 'axios'
import { ref } from 'vue'

// 成功したときに、ソード情報を入れる箱
const sword = ref(null)

// 失敗したときに、画面へ出す文章を入れる箱
const errorMessage = ref('')

// asyncを付けると、この関数の中でawaitを使える
const loadSword = async () => {
  try {
    // ソード情報が届くまで待つ
    const response = await axios.get('/sword.json')

    // 受け取ったソード情報を画面用の箱へ入れる
    sword.value = response.data
  } catch {
    // 失敗したとき、画面に出す文章を箱へ入れる
    errorMessage.value = 'ソード情報を受け取れませんでした'
  }
}
</script>

2つの書き方は、どちらも「成功」と「失敗」を扱えます。

書き方 成功したとき 失敗したとき
.then() / .catch() .then() の中 .catch() の中
async / await await の次の行 catch の中

今の自分には、最初のAxios記事では .then() / .catch() のほうが分かりやすそうです。

成功した後と失敗した後の場所が、最初からはっきり分かれているからです。

キャラクター 「今は `.then()` と `.catch()` で、成功と失敗の道を分けて見るほうが分かりやすそう。前回の書き方でも同じことはできるんだね」

次にやりたいこと

Axiosで受け取ったデータを使って、画面を少しずつ増やしたいです。

  • ソードを複数用意し、v-for で一覧表示する
    持ち物一覧のように、データ数に合わせてカードを並べてみたいです
  • ソードの画像もJSONへ追加する
    名前だけではなく、アイテムカードらしい画面にしてみたいです
  • わざとファイル名を変え、.catch() が動く場面を確認する
    失敗したときに、想定通り画面の文章が変わるか見てみたいです
  • ボタンを押したときにデータを読み込み直す
    利用者の操作で、画面の内容が変わる流れを試したいです
  • 前回の async / await の書き方と見比べる
    処理が増えたときに、どちらが自分には読みやすいか確認したいです

今日の整理

Axiosを使うときは、まずこの形を覚えておけばよさそうです。

<script setup>
import axios from 'axios'

// データを取りに行く
axios.get('/読み込みたいファイルやURL')
  .then((response) => {
    // 成功したときにすること
    console.log(response.data)
  })
  .catch(() => {
    // 失敗したときにすること
    console.log('データを受け取れませんでした')
  })
</script>
書き方 今の理解
npm install axios Axiosをプロジェクトへ追加する
import axios from 'axios' AxiosをVueファイルで使えるようにする
axios.get(...) データを取りに行く
.then(...) 成功した後にすることを書く
response.data 受け取ったデータを取り出す
.catch(...) 失敗した後にすることを書く

おわりに

Axiosを使うと、ソード情報を取りに行った後の成功と失敗を、.then().catch() で分けて書けることが分かりました。

前回の async / await と同じように、データが届くまで待つ必要はあります。ただ、今回は「成功したらソードを表示する」「失敗したら文章を表示する」と分かれて見えるので、自分には流れを追いやすく感じました。

次は、複数の画像解析結果や写真の情報を受け取って、カード一覧として表示する画面も試してみたいです。

学習中の内容なので、勘違いや理解不足もあると思います。もし気になる点があれば教えてもらえるとうれしいです。

 注意事項
 本ブログに掲載している内容は、私個人の見解であり、
 所属する組織の立場や戦略、意見を代表するものではありません。
 あくまでエンジニアとしての経験や考えを発信していますのでご了承ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?