Angularで非同期通信をする方法のメモを残して起きたいと思います。
TypeScriptもAngularにも明るくない人向けに限界まで砕いて書いておきます。
使用するバージョン
kuniatsu$ ng -v
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
@angular/cli: 1.1.3
node: 7.5.0
os: darwin x64
@angular/animations: 4.3.2
@angular/common: 4.3.2
@angular/compiler: 4.3.2
@angular/core: 4.3.2
@angular/forms: 4.3.2
@angular/http: 4.3.2
@angular/platform-browser: 4.3.2
@angular/platform-browser-dynamic: 4.3.2
@angular/router: 4.3.2
@angular/cli: 1.1.3
@angular/compiler-cli: 4.3.2
@angular/language-service: 4.3.2
kuniatsu$ npm -v
4.1.2
##フォルダ構成
ファイルはほとんど省略してます。
.
├── README.md
├── e2e
├── node_modules
├── src
│ ├── app
│ │ ├── app.component.css
│ │ ├── app.component.html
│ │ ├── app.component.ts
│ │ ├── app.component.spec.ts
│ │ └── app.module.ts
│ ├── assets
│ └── environments
├── .angular-cli.json
└── package.json
##app.module.ts
まず、app.module.tsにHttpModuleを追加します。
HttpModuleは、HTTPクライアントの機能を追加するためのモジュールです。
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import {HttpModule} from "@angular/http";//ここを追加
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpModule//ここを追加
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
##app.component.ts
次にapp.component.tsでgetの機能を実装します。
なるべく、TypeScriptを知らなくても読めるようにわざと長くかいてます。
気持ちJavaっぽく書いたつもりです。
import { Component } from '@angular/core';
import {Http, Response} from "@angular/http";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
private http:Http;
//非同期通信先のURLを指定する。
URL = 'assets/test.json';
//「コンストラクター」クラスが実体化された時に走る
constructor(http:Http){
this.http = http;
}
getMethod(){
//http.getをするためのオブジェクトを生成
var httpObj = this.http.get(this.URL);
//成功時・失敗時の動作を指定する。
httpObj.subscribe(this.getSuccess,this.getError);
}
//http.getが成功した時に走るメソッド
getSuccess(response:Response){
console.log(response.text());
}
//http.getが失敗した時に走るメソッド
getError(error){
console.log(error);
}
}
##app.component.html
app.component.tsで作った、メソッドgetMethod()が走るようにhtml側にクリックイベントを書きます。
<button (click)="getMethod()">Get!</button>
##test.json
このままでは読みに行くファイルがないので、app.component.tsのURLで指定したtest.jsonを作ります。
{
"name":"test.json",
"level":"easy"
}
作ったtest.jsonはassetsのフォルダの中に入れます。
.
├── README.md
├── e2e
├── node_modules
├── src
│ ├── app
│ │ ├── app.component.css
│ │ ├── app.component.html
│ │ ├── app.component.ts
│ │ ├── app.component.spec.ts
│ │ └── app.module.ts
│ ├── assets
│ │ └── test.json
│ └── environments
├── .angular-cli.json
└── package.json
##実行
これで、ng serveしアプリを実行します。
無事、作成したjsonの中身が取れていることがわかります。
##コンストラクターの書き方変更
ここからは、app.component.tsの書き方がTypeScriptっぽくないのでよくある書き方に変更していきます。
まず、コンストラクターの引数をメンバ変数に代入する場合、コンストラクターの引数のみに省略して書くことができます。
export class AppComponent {
private http:Http;
constructor(http:Http){
this.http = http;
}
}
こちらは下記のように書き換えることができます。
export class AppComponent {
constructor(private http:Http){}
}
##ラムダ式
次にES6で取入れられたラムダ式を使ってみます。
getSuccess(response:Response){
console.log(response.text());
}
こちらは、下記のように書き換えることができます。
getSuccess = response=>{
console.log(response.text());
}
##変数省略
さらに、変数に入れているものを直接書くことができるので、
getMethod(){
var httpObj = this.http.get(this.URL);
httpObj.subscribe(this.getSuccess,this.getError);
}
//http.getが成功した時に走るメソッド
getSuccess = response=>{
console.log(response.text());
}
}
こちらは、下記のように書き換えることができます。
getMethod(){
var httpObj = this.http.get(this.URL);
httpObj.subscribe(response=>{
console.log(response.text());
},
this.getError
);
}
これをerror側にもやると
getMethod(){
var httpObj = this.http.get(this.URL);
httpObj.subscribe(response=>{
console.log(response.text());
},error=>{
console.log(error);
});
}
と言う形になります。
最後に、httpObjもわざわざ変数に代入し直す必要はないので、
getMethod(){
this.http.get(this.URL)
.subscribe(response=>{
console.log(response.text());
},error=>{
console.log(error);
});
}
このように書くことができます。
##完成形
以上のことを踏まえて書くと、
import { Component } from '@angular/core';
import {Http, Response} from "@angular/http";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
//非同期通信先のURLを指定する。
URL = 'assets/test.json';
//コンストラクタークラスが実体化された時に走る
constructor(private http:Http){}
getMethod(){
this.http.get(this.URL)
.subscribe(response=>{
//成功時の処理
console.log(response.text());
},error=>{
//失敗時の処理
console.log(error);
});
}
ずいぶんスッキリ書けたのがわかります。