Help us understand the problem. What is going on with this article?

[axios] axios の導入と簡単な使い方

axios について、いくつか記事を書いておきながら導入についての記事を書いていなかったので、導入について記しつつ こちらの記事 で示した構成も作ってみた。

更新情報

  • 2018/05/15
    • axios へのリンクを更新しました( @ledsun 様、ご指摘ありがとうございました )(
  • 2018/07/02
    • axios のインスタンス生成時に指定している headers の内容を修正しました( @dyoshikawa 様、ご指摘ありがとうございました )

過去に書いた axios の記事

この記事を実施した環境

  • Windows10 Home 64bit macOS High Sierra( 10.13.4 )
  • nodist v0.8.8 ( in Windows10 )
  • n v2.1.7 ( in macOS High Sierra )
  • node v8.2.1 v9.4.0
  • npm v4.0.5 v6.1.0
  • Express v4.15.0 v4.16.0
  • axios v0.16.2 v0.18.0

前提

フロントエンド、バックエンドは Express で実装している。

axios とは

本家 によると

Promise based HTTP client for the browser and node.js

とある。
そのままな訳となるが、ブラウザや node.js で動く Promise ベースの HTTP クライアントである。 REST-API を実行したいときなど、これを使うと実装が簡単にできる。

axios の導入

次のコマンドを実行してインストールする。
一応 --save で package.json にも反映させておく。

$ npm install axios --save
package.json(抜粋)
{
  ...
  "dependencies": {
    "axios": "^0.16.2",
    ...
  },
  ...
}

axios を使ってバックエンド間のやり取りを行う

構成は次の感じ。

  1. バックエンドA はフロントエンドからのリクエストを受け付ける
  2. バックエンドA は「1.」を受けてバックエンドB へリクエストを投げる
  3. バックエンドB は「2.」を受けてレスポンスをバックエンドA へ返す
  4. バックエンドA は「3.」を受けてレスポンスをフロントエンドへ返す

シーケンス図にするとこんなイメージ。
sequence.png

バックエンドA の実装

  • ここでは上記の「1.」「2.」「4.」を担当する
  • バックエンドA はバックエンドB に対してリクエストを投げるので、ここが axios を利用する箇所となる
  • コード中の [] で囲った番号は上述の番号と合わせてある

GET メソッドだけの例となるが以下に実装例を示す

バックエンドAのindex.js
var express = require('express');
var router = express.Router();

// axios を require してインスタンスを生成する
const axiosBase = require('axios');
const axios = axiosBase.create({
  baseURL: 'http://localhost:4000', // バックエンドB のURL:port を指定する
  headers: {
    'Content-Type': 'application/json',
    'X-Requested-With': 'XMLHttpRequest'
  },
  responseType: 'json'  
});

// [1] フロントエンドからのリクエストを受け付けて
router.get('/', function(req, res, next) {

  // [2] バックエンドB に対してリクエストを投げる
  axios.get('/title')
  .then(function(response) {

    // [4] フロントエンドに対してレスポンスを返す
    res.render('index', response.data);
  })
  .catch(function(error) {
    console.log('ERROR!! occurred in Backend.')
  });
});

module.exports = router;

オプションを指定したい場合、 GET メソッドでは axios.get(url, option) として第2引数にセットする。 PUT や POST メソッドの場合は第3引数にセットする。
本家のこちらあたり が参考になるかと。

バックエンドB の実装

  • ここでは上記の「3.」を担当する
  • こちらは単純にリクエストに対してレスポンスを返すだけなので axios は登場しない
  • シンプルに Express だけの実装となる
  • コード中の[]で囲った番号は上述の番号と合わせてある
バックエンドBのindex.js
var express = require('express');
var router = express.Router();

// [3] フロントエンドA からのリクエストを受けてレスポンスを返す
router.get('/title', function(req, res, next) {
  res.json({ title: 'Express. Responded by BackEnd-B.' });
});

module.exports = router;
  • なお、バックエンドB ではポート番号を変える必要があるので、忘れずに次の部分を修正しておく
bin/www
// 15行目
// デフォルトでは 3000 が指定されているが、そのままではバックエンドA とポート番号が重複するので変更する
// (順序が逆になるが) ここではバックエンドA で指定しているポート番号[4000]を設定する
var port = normalizePort(process.env.PORT || '4000');

動作確認

  1. バックエンドA、バックエンドB をそれぞれ次のコマンドで起動させる

    バックエンドAを起動する
    $ npm start
    
    バックエンドBを起動する
    $ npm start
    
  2. バックエンドA に対してブラウザからアクセスする。

  • バックエンドA の URL(http://localhost:3000) にアクセス
  • バックエンドB で返しているレスポンスである 「 Express. Responded BackEnd-B. 」 が表示されていることが確認できる

    Responded by BackEnd-B.png

終わりに

axios を利用すると REST-API を使ってのやり取りが簡単に実装できた。
で、蛇足ながら。。。
使用する REST-API が少ない場合は上記例のように axios.get(url) のように個別に書くのもいいが、API が増えてくるとちょっと冗長である。
というところで、 REST-API を実行する際の入り口として次のようなヤツを用意するのもアリかと思う。

rest-facade.js(REST-APIを実行する際の入り口)
// axios を require してインスタンスを生成する
const axiosBase = require('axios');
const axios = axiosBase.create({
  baseURL: 'http://localhost:4000', // バックエンドB のURL:port を指定する
  headers: {
    'Content-Type': 'application/json',
    'X-Requested-With': 'XMLHttpRequest'
  },
  responseType: 'json'  
});

/**
 * REST-API の GET メソッドを実行する
 *
 * @param {any} url REST-API のURL
 * @param {any} callback 呼び出し元のコールバック処理
 * @param {any} [option=null] axios のオプション
 */
function get(url, callback, option = null) {

  // axios を使って引数で指定された url に対してリクエストを投げる
  axios.get(url, option)
  .then(function(response) {

    // 返ってきたレスポンスはそのまま加工せずに callback で呼び出し元へ渡す
    callback(response);
  })
  .catch(function(error) {
    console.log('ERROR!! occurred in Backend.')
  });
}

/**
 * コンストラクタ
 */
function RestFacade() {}

// prototype チェインに突っ込む
RestFacade.prototype.get = get;

module.exports = new RestFacade();
rest-facade.jsを使う側
const express = require('express');
const router = express.Router();
const restFacade= require('./rest-facade');

router.get('/', function(req, res, next) {
  restFacade.get('/title', function(response) {
    res.render('index', { title: response.data.title });
  });
});

補足

プロキシ関連の設定( Error: getaddrinfo ENOTFOUND の対処 )

プロキシを使用する環境下で、axios で REST-API を実行した際に次のエラーが発生するケースがある。

エラー情報
Error: getaddrinfo ENOTFOUND proxy.host.address(1) proxy.host.address(2):NNNN(3)

# (1), (2) の proxy.host.address は自身の環境におけるプロキシのアドレス
# (3) の NNNN はポート番号

で、axios 経由で REST-API を実行するときにプロキシを経由したくない場合、次の設定を前述のインスタンス生成時にセットしてやれば良い。

バックエンドAのindex.jsからaxiosをrequireしてインスタンスを生成する箇所を抜粋
const axiosBase = require('axios');
const axios = axiosBase.create({
  baseURL: 'http://localhost:4000', // バックエンドB のURL:port を指定する
  headers: {
    'Content-Type': 'application/json',
    'X-Requested-With': 'XMLHttpRequest'
  },

  // -------------------------
  // プロキシを無視する設定
  // -------------------------
  proxy: false,

  responseType: 'json'  
});

プロキシ周りの設定については 本家の Request Config にプロキシについての記述があるので参考にどうぞ。

ksh-fthr
フロントエンドは Angular, バックエンドは Express / axios / Sequelize 等を使ってましたが今は Rails で奮闘中。 最近 Vue.js も触り始めました。あと Docker 使って環境構築なんかにも手をだしてます。 モノをつくって共有、というよりはその過程で得たものを共有できればいいなぁと思ってます。 どうぞよろしくお願いします。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした