RitoLabo

Vue.jsでのAPIリクエストをaxios&RepositoryFactoryパターンで実装する

  • 公開:
  • 更新:
  • カテゴリ: JavaScript Vue.js
  • タグ: JavaScript,Factory,Vue,API,Repository,axios

Vue.jsに限らずJavaScriptフレームワークでフロントエンドを実装していると、アプリケーションによって データを取得したりなど、外部のAPIなどと通信を行う機会も多く発生します。

今回、API周りを良い感じに実装できるパターンが無いかなと探していたところ、以下の記事でRepository&Factoryパターンでの実装パターンを紹介していました。

【Vue.js】Web API通信のデザインパターン
https://qiita.com/07JP27/items/0923cbe3b6435c19d761

今回はVue.jsでのAPIリクエストをaxios&RepositoryFactoryで実装してみます。

アジェンダ
  1. 開発環境
  2. axios
    1. インストール
  3. RepositoryFactoryパターン
  4. Repository
  5. userRepository
  6. RepositoryFactory
  7. コンポーネント実装
  8. バックエンド側処理

開発環境

今回の開発環境は以下の通りです。

  • Vue.js 2.x
  • Vue CLI 3.x
  • axios 0.18.0
  • Node.js 12.x
  • npm 6.5

axios

axiosは、ブラウザ及びnode.js用のPromiseベースのHTTPクライアントです。

axios
https://github.com/axios/axios

  • ブラウザからXMLHttpRequestsを作成する
  • node.jsからhttpリクエストを行う
  • Promise APIをサポート
  • リクエスト・レスポンス内容の出力(interceptors)
  • リクエスト及びレスポンスデータの変換
  • リクエストのキャンセル
  • JSONデータの自動変換
  • XSRFから保護するためのクライアント側のサポート

今回はaxiosを使ってサーバ側へリクエストを投げます。

インストール

axiosのインストールはnpmなら以下コマンドで出来ます。

npm install axios

その他、yarn/bowerでもインストール可能。詳細は公式参照。

RepositoryFactoryパターン

Repositoryパターンは永続化の隠蔽、Factoryパターン(ここではFactoryMethodの方)はオブジェクトの生成に関するデザインパターン。

紹介記事ではRepositoryFactoryとして、RepositoryパターンとFactory(FactoryMeyhod)パターンの両方を用いて実装しています。

Repository

では実装してみます。まずは大本のリソースを定義します。

Repository.js
import axios from 'axios'

const baseDomain = 'localhost:8000'
const baseURL = `http://${baseDomain}`

export default axios.create({
baseURL: baseURL
})

変更の必要の無い部分をベースのURLとしてaxiosのインスタンス生成時に渡しています。

userRepository

次はエンティティのリソース定義です。 今回はユーザーに関するCRUD操作を仮定して、userRepositoryを作成します。

userRepository.js
import Repository from './Repository'

const resource = 'store.php'

export default {
register (payload) {
Repository.defaults.headers.post['Content-Type'] = 'multipart/form-data'

return Repository.post(`${resource}`, payload)
}
}

ユーザー登録を想定して記述しています。画像などのファイルもアップロードするので、 ContentTypeをmultipart/form-dataに指定しています。

例えばユーザー情報を取得したりする場合には、ここにメソッドを追加していく流れになります。

RepositoryFactory

続いてFactoryです。

RepositoryFactory.js
import userRepository from './userRepository'

const repositories = {
user: userRepository,
}

export const RepositoryFactory = {
get: name => repositories[name]
}

repositories に必要なリポジトリを登録していき、RepositoryFactory のgetメソッドで必要なリポジトリを取得する流れです。

コンポーネント実装

これらを使用する為にコンポーネント側を実装します。

sameComponent.vue
import { RepositoryFactory } from "./Repositories/RepositoryFactory";
const UserRepository = RepositoryFactory.get('user')

export default {
/*
* 省略
*/
methods: {
async send () {
const response = await UserRepository.register({/* something form data */})
if (response.data.success) {
this._sendSuccess(response)
} else {
this._sendError(response.data.message)
}
}
/*
* 省略
*/

Repository使用部分のみ抜粋して記載しています。 FactoryからUserRepositoryを取得し、registerメソッドでフォームデータを投げています。

バックエンド側処理

このセクションはおまけです。今回リクエストを投げる関係で折角なら一通り動作させたいので、PHPで簡単に受け側を実装しました。

store.php
<?php
header("Access-Control-Allow-Origin: *");

if(!empty($_FILES)) {
$file_path_dir = "uploads";

try {
foreach ($_FILES as $key => $file) {
$store_path = sprintf("%s/%s", $file_path_dir, $file['name']);

if (!move_uploaded_file($file['tmp_name'], $store_path)) {
throw new Exception('ファイルの保存に失敗しました');
}
}
$response = [
'success' => true,
'message' => ''
];
} catch(Exception $e) {
$response = [
'success' => false,
'message' => $e->getMessage()
];
}

echo json_encode($response);

} else {
echo json_encode([
'success' => false,
'message' => 'FILE None'
]);
}

データベースは使いませんが、代わりにファイルを保存します。 処理後は、結果をjsonで返します。

もしMacでPHPが動作する環境であれば、以下のコマンドで開発用ビルトインウェブサーバーを起動できます。

# ドキュメントルートへ移動
cd /path/to/project

# ビルトインウェブサーバーの起動
php -S localhost:8000

まとめ

RepositoryFactoryを用いるとそれぞれが分離されて、拡張や保守も簡単になります。
コンポーネント側の実装もaxiosやAPI部分が隠蔽されているのでコードもすっきりしていていい感じです。
JavaScriptでもしっかり設計して実装していきたいですね。

サンプルコード