見出し画像

作りながら学ぶVue.js パート5【APIリクエスト/非同期処理】

このnoteは、JavaScriptのフレームワークであるVue.jsを初心者でも扱えるようになることを目指して、実際にアプリケーションを作りながら学んでいくチュートリアルです。

前のパートでは、入力フォームの部分を作りながらdataやv-modelといった、Vue.jsで開発を行う上で重要なポイントについて学びました。

今回は入力フォームでボタンを押した時の動作について解説していきます。

前回の課題について

本題に入る前に前回のパートの最後に出題した課題の答えを載せておきます。

まずは

・inputの値を保持するための入れ物としてのdataであるinputValue
・inputの上に表示するための入れ物としてのdataであるdisplayValue

を用意します。

そしてinputTextとinputを双方向に紐づけるためにinputにv-modelディレクティブを追加します。

そして追加ボタンを押した時に動作するメソッドとして、inputValueをdisplayValueに代入するmove()を用意します。

最後にボタンを押した際に上で用意したmoveが実行されるようにbuttonにv-onを設定してイベントハンドリングを行います。

前回お話した内容を踏まえていれば理解できる実装かと思います。ピンとこない人はパート4の復習をしてみてください。

<template>
 <div id="app">
   <div>{{ displayValue }}</div>
   <div>
     <input type="text" v-model="inputValue">
   </div>
   <div>
     <button v-on:click="move">追加</button>
   </div>
 </div>
</template>

<script>
export default {
 name: "app",
 data() {
   return {
     inputValue: "",
     displayValue: ""
   };
 },
 methods: {
   move() {
     this.displayValue = this.inputValue;
   }
 }
};
</script>

<style lang="scss">
#app {
 font-family: "Avenir", Helvetica, Arial, sans-serif;
 -webkit-font-smoothing: antialiased;
 -moz-osx-font-smoothing: grayscale;
 text-align: center;
 color: #2c3e50;
 margin-top: 60px;
}
</style>

今回学ぶ内容について

今回学びながら実装していくのはこの部分。

<script>
export default {
 data() {
   return {
     inputTitle: "",
     inputPeriod: "",
     inputDetail: ""
   };
 },
 methods: {
     createTask() {
         // タスクを作成する処理
     }
 }
};
</script>

実際に入力した内容に基づいて、タスクを作成する処理です。

では早速実装していきましょう…と言いたいところなのですが、この部分を実装するにあたって予備知識が必要ですので説明しておきます。

API通信について

Vue.jsなどで今回のようなWebアプリケーションを開発する場合、API(WebAPIと呼ぶこともある)と言うものと連携する必要が出てきます。

フロントエンド側では画面の表示やユーザー操作による画面の更新に専念して、データベースへの保存や複雑な計算処理などはAPIサーバーと言うものを用意してそこで行う、と言うのがVue.jsを使うような開発現場における一般的な構成です。

今回はタスク管理Webアプリケーションのフロントエンド部分を開発しているわけですが、Vue.jsだけだとユーザーが入力したデータを保存したり、過去に登録したタスクを参照したり、と言うことができません。

そのためAPIサーバーを用意して、そのサーバーと連携する必要が出てくるわけです。

ただ今回はあくまでVue.jsを用いたフロントエンド開発がテーマですので、こちらでAPIサーバーを用意しておきました。最初に導入してもらったNode.jsを使って構築された簡易的なAPIサーバーです。

こちらのソースコードをgit cloneし実行することによって、localhost:3000と言うアドレスに対してアクセスすることで通信可能なAPIサーバーとして動作します。

> git clone https://github.com/tis-engineer/vue-make-learn-api.git
> cd vue-make-learn-api
> node index.js

このAPIサーバーを利用する形でタスク管理アプリのデータ保存などを行う形になります。

このサーバーを終了させたいときは、node index.jsを実行した画面でctrl + cを押下してください。

ちなみにこのAPIサーバーの概要については以下の記事で紹介しています。詳細は少しいじっていますが、基本的な構成が気になる方はご覧になってみてください。

もちろん全世界に公開されるアプリケーションを作るときなどはAWSVPSなどにサーバーを構築して、そこでAPIサーバーを動かす必要がありますので、そこは覚えておきましょう。

では予備知識と準備が完了したところでようやくタスク作成処理の解説に進みます。

API通信の準備をする

上で起動したAPIサーバーに対してアクセスをするのにはHTTP通信を以下の部分で行う必要があります。

createTask() {
  // タスクを作成する処理
}

JavaScriptでHTTP通信を行おうとした場合、JavaScriptに組み込まれているXMLHttpRequestfetchjQueryのajaxを使う方法など様々ありますが、Vue.jsで開発をする場合、axiosというライブラリを使うことが多いです。

早速このaxiosを取得しておきます。

yarn add axios

そしてこのaxiosというライブラリをそのままコンポーネントのvueファイルでimportして使うのもいいのですが、共通処理を挟みたい時や、今回で言うlocalhost:3000のようなホスト部分を繰り返し書かないで済むようにモジュール化するアプローチをとりましょう。

モジュール化とは何か、についてお話すると初心者の方には難しく、混乱を招く恐れがあるので、今はHTTP通信を実現するための機能を別ファイルに切り出している、程度に認識しておいてもらえればOKです。

まずはsrcディレクトリ配下にapi.jsと言うファイルを作成します。あくまでJavaScriptのロジックを用意する場所なので、拡張子は.vueではなく、.jsです。

そして作成したら以下のような実装を行います。

src/api.js

import axios from "axios";

const baseURL = "http://localhost:3000";

export default axios.create({
   baseURL
});

今回は行いませんが、例えばAPIにリクエストした際に共通の処理を行いたい時や、タイムアウトまでの時間を設定したい場合などはaxiosのプロパティをいじって共通の設定を行う形になります。

詳しくはaxiosのGitHubに詳しく解説されていますので、気になる方はチェックしてみてください。

vueファイルでHTTP通信を実行

次にこの作成したHTTP通信用のモジュールを使ってフォーム部分でタスクの作成ができるようにします。

<script>
import api from "@/api";
export default {
 data() {
   return {
     inputTitle: "",
     inputPeriod: "",
     inputDetail: ""
   };
 },
 methods: {
   async createTask() {
     const result = await api.post("/tasks", {
       title: this.inputTitle,
       period: this.inputPeriod,
       detail: this.inputDetail
     });
     console.log(result);
   }
 }
};
</script>

作成したapiモジュールをインポートして、createTask()メソッドでaxiosのpostメソッドを呼び出すと言う手順です。

postメソッドの引数①には対象のAPIのパスを、引数②にはPOSTするデータを設定しています。thisを使ってv-modelによって更新されているdataを引っ張ってきていますね。

そしてここでは一旦レスポンスをそのままログに出力させています。

async/awaitについて

ここでasync/awaitという、人によっては見慣れないワードが出ています。

これはJavaScriptで実用的なアプリケーションを開発する際には欠かせない非同期処理を実現するためのキーワードです。

そしてこの非同期処理とasync/awaitをしっかりと理解するためには更にPromiseと言う考え方についても理解する必要があります。

非同期処理は簡単に言えば、ある処理Aを実行しながら別の処理Bを走らせておく、といったイメージ。

そしてPromiseと言うのは、別で走らせておいた処理Bが完了(または失敗)したことを処理Aに対して伝えるための機能を持った存在です。

今回の例で言えば、処理AがcreateTask()、処理BがAPIサーバーへのリクエスト。と言うことになります。

もしこの時に非同期処理を用いない場合、APIサーバーへのリクエストに時間がかかった場合、他のフロントエンドの処理が一切行えなくなってしまいます

そのような事態が発生して、ユーザーの操作性を損なったりしないように非同期処理という考え方が必要になるわけです。

そしてこの非同期処理は聞いたことのある方もいるかとは思いますが、コールバックと言うものを使うことでも実現できます。

ただコールバックを使って複雑な処理を実装するとコードの見通しが悪くなりやすいため、最近ではPromiseの概念を用いた実装が主流となっています。

そして更に最近ではPromiseをより通常の処理と同じ感覚で利用することができるawait/asyncを用いた非同期処理の実装が一般的となってきています。

この非同期処理・Promise・async/awaitについて初心者の方に向け分かりやすく説明しようとすると、それだけで1記事以上のボリュームが想定され、Vue.jsのチュートリアルとしてのスコープから外れてしまうため、詳細な解説は割愛させてもらいます。

async createTask() {
  const result = await api.post("/tasks", {
    title: this.inputTitle,
    period: this.inputPeriod,
    detail: this.inputDetail
  });
  console.log(result);
}

ここでは

・awaitというキーワードをPromiseを返す関数(非同期で行わせたい処理)の呼び出しの前につけると、その関数が完了するまでその場で待機される

・現状awaitを使うためにはasyncが冒頭についた関数の中である必要がある

と言う理由からこのような記述になっていると覚えておいてください。

ちなみにasync/awaitは比較的新しい書き方なので、Promiseで同じ処理を実装する例も載せておきます。こちらの方が分かりやすい、と言う場合はこちらで実装する形にしても問題ありません。

methods: {
  createTask() {
    api.post("/tasks",{
      title: this.inputTitle,
      period: this.inputPeriod,
      detail: this.inputDetail
    }).then(result => {
      console.log(result);
    });
  }
}

ただasync/awaitの方がより直感的に非同期処理を実現できるため、今後の解説は基本的にasync/awaitをベースに解説していきます。

他サイトの情報で恐縮ではありますが、以下の記事などでJavaScriptにおける非同期処理・Promiseについて学び、

以下の記事でasync/awaitを使って、非同期処理をより便利に扱えるのか、といった流れで学習してみることをオススメいたします。

僕もあまり賢い方ではないので、最初のうちはPromiseを理解するまでとても時間がかかりました。

なので最初から全部理解しようとすると、しんどくなってしまう気持ちはとてもよく理解できます。

とはいえ非常に重要な考え方ですので、最低限「なぜPromiseやasync/awaitが必要になってくるのか」と言う部分については理解した上で先に進むことをオススメします。

まとめ

このままFormを画面に表示させ、細かい調整を加えて行きたいところなのですが、かなりボリュームが大きくなってしまったため、次パートに回させていただきます。

次回はこちら


この記事が気に入ったらサポートをしてみませんか?