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の使い方の初歩的なミス

Last updated at Posted at 2024-09-12

こんにちは。

Node.jsを学習している際に、フロント側からバックエンド側に通信しようとした際につまずきました。
もう少し詳しく書くと、フロント側でaxiosを使ってバックエンド側APIにアクセスし、APIの中でres.redirect()によって画面遷移するのに失敗しました。

ファイル構成は下記のようになっています。
キャプチャ.PNG

それぞれのファイルの中身は下記のようになっています。

index.js
const express = require('express')
const path = require('path')

const app = express()

app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'ejs')

app.get('/test1', (req, res) => {
  res.render('test1')
})

app.get('/test2', (req, res) => {
  res.redirect('/test3')
})

app.get('/test3', (req, res) => {
  res.render('test3')
})

app.listen(3000, () => {
  console.log("Server starts at http://localhost:3000")
})
test1.ejs
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>test1</title>
</head>
<body>
  <!-- axiosパッケージをインポートする -->
  <script src="https://unpkg.com/axios@1.6.7/dist/axios.min.js"></script>
  <h2>I am test1</h2>
  <button>クリック</button>
  <script>
    document.querySelector('button').addEventListener('click', async () => {
      await axios.get('/test2')
    })
  </script>
</body>
</html>
test3.ejs
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>test3</title>
</head>
<body>
  <h2>I am test3</h2>
</body>
</html>

なお、test1.ejsで表示されるのは下記のようなシンプルの画面になっています。
キャプチャ.PNG

コードからなんとなく意図を読み取れるかもしれませんが、やりたいのはクリックボタンを押し、バックエンド(index.js)のapp.get('/test2', ...)にリクエストを投げ、さらにapp.get('/test3', ...)にリクエストを投げることでtest3.ejsの画面に遷移すること。
回りくどいですが、res.render()res.redirect()の動作確認のためこんな風に記述しました。
みなさんにとってはばかばかしいミスと思うかもしれません。もちろん上記のコードでは、ボタンを押しても何の反応もありませんでした。実際私は、axios.get()を使えば指定したパスにアクセスして、パス内の処理を勝手にしてくれるものだと思っていた。ここでaxiosについてもう一度調べました。
axiosは、PromiseベースのHTTPクライアントライブラリであり、axiosのリクエストメソッド(get, post, deleteなど)はPromiseオブジェクトを返してくれます。
つまり、test1.ejs内のコードaxios.get('/test2')では何かしらの返り値が返ってきているはずです。そこでtest1.ejsのの部分を下記のように修正し、返り値を確認してみました。

test1.ejs
<script>
  document.querySelector('button').addEventListener('click', async () => {
    const response = await axios.get('/test2')
    console.log(response)
  })
</script>

そこで下記オブジェクトが帰ってきました。
キャプチャ.PNG

ここで見ると、requestプロパティの下のresponseURLにアクセスしたいURLが入っていることがわかりました。これは、index.jsの中のapp.get('/test2', ...)res.redirect('/test3')が、「"http://localhost:3000/test3"に飛んでくださいね。」と言っているようなイメージです。つまり、意図していたことを実現するためには、このアドレスを返り値から取得し、test1.ejsを下記のように書き換えればOKです。

test1.ejs
<script>
  document.querySelector('button').addEventListener('click', async () => {
    const response = await axios.get('/test2')
    // response.request.responseURL: http://localhost:3000/test3
    location.href = response.request.responseURL
  })
</script>

これで、ボタンをクリックすると無事test3.ejsの画面に遷移できました。

結論を言うと、axiosはPromiseベースのライブラリで、使用する際は必ず返り値を受け取る必要があります。
今まで見よう見まねでaxiosを使うことがあったが、いざ自分でコードを書くと、深く考えずに使っていた弊害がもろに出てしまった。

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?