こんにちは。
Node.js
を学習している際に、フロント側からバックエンド側に通信しようとした際につまずきました。
もう少し詳しく書くと、フロント側でaxios
を使ってバックエンド側APIにアクセスし、APIの中でres.redirect()
によって画面遷移するのに失敗しました。
それぞれのファイルの中身は下記のようになっています。
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")
})
<!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>
<!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で表示されるのは下記のようなシンプルの画面になっています。
コードからなんとなく意図を読み取れるかもしれませんが、やりたいのはクリックボタンを押し、バックエンド(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>
document.querySelector('button').addEventListener('click', async () => {
const response = await axios.get('/test2')
console.log(response)
})
</script>
ここで見ると、requestプロパティの下のresponseURLにアクセスしたいURLが入っていることがわかりました。これは、index.jsの中のapp.get('/test2', ...)
のres.redirect('/test3')
が、「"http://localhost:3000/test3"に飛んでくださいね。」と言っているようなイメージです。つまり、意図していたことを実現するためには、このアドレスを返り値から取得し、test1.ejsを下記のように書き換えればOKです。
<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を使うことがあったが、いざ自分でコードを書くと、深く考えずに使っていた弊害がもろに出てしまった。