axiosの使い方の初歩的なミス

こんにちは。

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

ファイル構成は下記のようになっています。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3532036/d4b3a64a-8ae5-4901-4483-9b790d8bf25d.png)

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

```javascript: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")
})
```

```html: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>
```

```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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3532036/434f47d3-5788-b455-9e8e-0be23f1daef4.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の<script></script>の部分を下記のように修正し、返り値を確認してみました。

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

そこで下記オブジェクトが帰ってきました。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3532036/29df1027-461e-eac3-4334-bf45170555a6.png)

ここで見ると、requestプロパティの下のresponseURLにアクセスしたいURLが入っていることがわかりました。これは、index.jsの中の`app.get('/test2', ...)`の`res.redirect('/test3')`が、「"http:\//localhost:3000/test3"に飛んでくださいね。」と言っているようなイメージです。つまり、意図していたことを実現するためには、このアドレスを返り値から取得し、test1.ejsを下記のように書き換えればOKです。
```html: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を使うことがあったが、いざ自分でコードを書くと、深く考えずに使っていた弊害がもろに出てしまった。