【Axios入門】Node.jsでAxiosを使用しました

# Axios入門

**Axiosとは**
> Node.jsとブラウザのための`Promise`ベースのHTTPクライアントです。これは `Isomorphic（`= 同じコードベースでブラウザと Node.js の両方で実行できる）と呼ばれます。 サーバー側ではネイティブ の Node.js `http` モジュールを使用し、クライアント (ブラウザ) では `XMLHttpRequests` を使用します。

**特徴**
1. ブラウザから`XMLHttpRequests`を作成する
2. Node.jsから`http`リクエストを作成する
3. `Promise`APIをサポート
4. `インターセプト`のリクエストとレスポンス
5. リクエストとレスポンスのデータを変換
6. リクエストをキャンセル
7. JSONデータの自動変換
8. `XSRF`から保護するためのクライアント側のサポート


**Axiosのインストール**
npmを利用して：
```js
npm install axios
```


**GETリクエストの例**
Promise形式の場合：
```js
const axios = require('axios');

// クエリパラメータ付きのリクエスト
axios.get('/user?userId=12345')
    .then((response) => {
        // handle success
        console.log(response);
    })
    .catch((error) => {
        // handle error
        console.log(error)
    })
    .finally(() => {
        console.log(`always executed`);
    });

// 上記と同じ結果
axios.get('/user', {
        params: {
            userId: 12345
        }
    })
    .then((response) => {
        // handle success
        console.log(response);
    })
    .catch((error) => {
        // handle error
        console.log(error)
    })
    .finally(() => {
        console.log(`always executed`);
    });
```

`async/await`形式の場合(ECMAScript 2017以降に対応した環境で動く)：
```js
const axios = require('axios');

const getUser = async () => {
    try {
        const response = await axios.get('/user?userId=12345');
        console.log(response);
    } catch (error) {
        console.error(error);
    }
} 
```

上記の例を、`express`で試してみます。まず、フォルダ構成は以下の通り：
```
.
├─controllers
│  └─userController.js
├─routes
│  └─user.js
└─views
│  └─user.pug
├─app.js
└─package.json
```

次に、使用したモジュールが
```
"express": "^4.18.2",
"axios": "^1.4.0",
"pug": "^3.0.2",
"nodemon": "^2.0.22"
```
となっています。`express`と`axios`は本題なので説明をスキップします。
`pug`は`express`で使用される`view engine`の1つです。今回は勉強のために画面を作成してAPIを呼び出すという方式をとっており、画面を`pug`で作成しています。
`nodemon`はファイルの変更を検知し、そのたびにサーバーを再起動してくれるツールです。開発のときに便利なので使用しています。`nodemon`を使用するために、`package.json`のキー`scripts`内に
```json:pacakge.json
"scripts": {
    "start": "nodemon app.js"
}
```
と記載し、node.jsの実行を`npm run start`により行っています。
コードの読み込みの流れとしては`app.js`→`routes/user.js`→`controllers/userController.js`なのでこの順番でコードを記載します。

```js: app.js
////Require Setup///////////////////////////
const express = require('express');
const path = require('path');
const userRouter = require('./routes/user');
////////////////////////////////////////////

const app = express();

////View Engine Setup///////////////////////
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
////////////////////////////////////////////

////App Setup//////////////////////////////
app.use(express.json())
app.use(express.urlencoded({extended: true}))
app.use('/', userRouter);
////////////////////////////////////////////

////Server Setup///////////////////////////
const hostname = '127.0.0.1'
const port = '5000'
app.listen(port, hostname, () => {
    console.log(`*** Server is running at http://${hostname}:${port} ***`)
})
////////////////////////////////////////////
```
注：画面にJSON形式のデータを表示するため`App Setup`内に、`express.json()`と`express.urlencoded({extended: true})`を記載しています。

```js: routes/user.js
const express = require('express');
const router = express.Router();

////Require Controllers//////////////////////
const user_controller = require('../controllers/userController');
////////////////////////////////////////////

/** GET USER PAGE */
router.get('/', user_controller.user_page);

/** POST API CALL */
router.post('/api', user_controller.call_api);

////Router Exports//////////////////////////
module.exports = router;
////////////////////////////////////////////
```

```js: controllers/userController.js
////Require Setup////////////////////////////
const axios = require('axios');
////////////////////////////////////////////

exports.user_page = (req, res) => {
    res.render('user')
}
exports.call_api = (req, res) => {
    const {METHOD,endPoint,ID} = req.body
    const url = 'https://qiita.com/'
    const callURL = url + endPoint
    let data;
    axios.get(callURL)
    .then((response) => {
        data = response.data
        res.json(data)
    })
    .catch((error) => {
        // handle error
        console.log(error)
    })
    .finally(() => {
        console.log(`always executed`);
    });
}
```
`userController.js`内でやっと`axios`が登場しています。(呼び出すだけであれば、`app.js`内でよかったですね。)
また、今回使用したAPIは`Qiita API`で、[こちらの記事](https://qiita.com/oriefield/items/4355a637725a97d2be31)で必要な箇所はまとめています。今回はGET送信のみを使用したので、アクセストークンは必要ありません。(今回の記事のためだけにまとめたまでありますね。)
注意点としては、APIによってレスポンスの返し方を変える必要があります。今回使用したAPIのエンドポイントは`api/v2/schema`でしたが、こちらは上記の実装で画面表示は問題ありません。一方で、記事の一覧を取得するために`/api/v2/items`を呼び出した場合、`response.data`が配列になるので、例えば`res.json(data[0])`のようにデータのアクセス方法を変える必要があります。

最後に、画面がこちら：
```pug: user.pug
doctype html
html(lang="ja")
    head
        // Required meta tags
        meta(charset="utf-8")
        meta(name="viewport" content="width=device-width, initial-scale=1")
        // Bootstrap CSS
        link(href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous")
        title=title
    body
        div(class="container")
            h1 USER
            form(action="/api" method="POST")
                div(class="mb-3")
                    label(for="METHOD" class="form-label") Http Method
                        select(class="form-select" aria-label="Default select example" id="METHOD" name="METHOD")
                            option(selected) Select HTTP method
                            option(value="GET") GET
                            option(value="POST") POST
                            option(value="PUT") PUT
                            option(value="PATCH") PATCH
                            option(value="DELETE") DELETE
                    br
                    label(for="endPoint" class="form-label") End Point URL(Relative)
                    input(type="text" class="form-control" id="endPoint" name="endPoint")
                    label(for="ID" class="form-label") Parameter(ID)
                    input(type="text" class="form-control" id="ID" name="ID")
                    button(type="submit" class="btn btn-primary") Submit
            
        script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous")
```
大まかに、`Bootstrap5`を使用しており、そこからコンポーネントを拝借。データもHttpメソッドとURL、パラメータを入力して送信するという簡素なものです。（今回はメソッドとパラメータは無視しているので、今後はこちらを改良していきたい。）

## 最後にまとめ（感想）
`Axios`を調べて、今回この記事をまとめたわけですが、まだ`GET`送信しかまとめられていません。大半は`express`による実装部分の記事となっています。パラメーターも画面で受け取れるように実装していきたいです（JSON形式にして受け取るのがよさそうです）。
次回以降は`POST`送信についてまとめていきたいと思います。（使用用途を考えるのは大変ですが、シンプルに構文をまとめるよりかは面白いのでこんな感じの記事でやっていきたいと思いました。
また、expressでの実装時のファイル名はuserじゃなくてよかったですね。）