Angularチュートリアルをやる 6日目
■ 思ったこと
最終章までたどり着いたぞ!!
■ 6. HTTPサービスの有効化
HTTPリクエストを介してHeroService
がデータを取得できるようにしょう!HTTPを通してデータの保存ができるようになるとな、APIとかのことかね?
HttpClient
HTTPを通してリモートサーバーと通信するための仕組み。app.modual.ts
にHttpClientModule
をインポートして、imports
配列にセットすれば準備はOK
In-memory Web APIをインストールしよう
今回は「In-memory Web API」を使ってリモートサーバーとの通信を再現するぞ、モックサーバーみたいなものだと理解!使うにはnpm install angular-in-memory-web-api --save
でパッケージをインストールしよう
app.module.tsにサービスをimport
- インストールしたパッケージから
HttpClientInMemoryWebApiModule
と、これから作成するクラスInMemoryDataService
をあらかじめインポートする imports
配列にはHttpClientInMemoryWebApiModule
にforRoot()
をチェーンして、データ取得元となるInMemoryDataService
を引数に持たせよう
imports: [ … HttpClientModule, HttpClientInMemoryWebApiModule.forRoot(InMemoryDataService, { dataEncapsulation: false }), ],
InMemoryDataServiceを作るのだ
- HTTPでデータをやり取りする用のサービスが必要、
ng generate service InMemoryData
でサクっと作ろう - 大事なのは
createDb()
、InMemoryDbService
を実装するべし - heroes.tsで定義していたモックデータを
createDb()
の返り値にすればOK
export class InMemoryDataService implements InMemoryDbService { createDb() { const heroes = [ { id: 1, name: 'warrior' }, { id: 2, name: 'thief' }, { id: 3, name: 'robot' }, { id: 4, name: 'inventor' }, { id: 5, name: 'witch' }, { id: 6, name: 'jester' }, ]; return { heroes }; }
HeroServiceをHTTP対応仕様に変更セヨ
- まずはconstructorに
HttpClient
を追加する - 次にAPIのURLを定義しよう、
createDb()
で設定した戻り値heroes
がURLとなるぞ! - サーバーからデータの取得には
http.get()<>
を使う、引数に設定したエンドポイントにデータを取りに行ってくれるぞ - 今回は
of(HEROES)
をhttp.get<Hero[]>(this.heroesUrl)
に書き換えればOK - すべてのHttpClientメソッドは
Observable
を返すので、戻り値は変わらずObservable<Hero[]>
となる
エラーハンドリングも必要だ
getHeroes()
が失敗することもまぁあるでしょう。失敗したとしても、結果としてObservable
が返ってくれば問題ないのでObservable.pipe()
を使ってどうにかしよう、pipe=パイプ、複数の機能を一個にまとめられる、便利Observable
はpipe()
で値を加工できる(Promiseのthen的な)- 今回は
pipe()
に失敗したObservable
処理用のcatchError
オペレーターを設定しマス - 正常な
Observable
が返ってくれば処理が続くのでcatchError()
の引数にhandleError()
を渡してそこで処理してもらおう
getHeroes(): Observable<Hero[]> { return this.http.get<Hero[]>(this.heroesUrl) .pipe( catchError(this.handleError<Hero[]>('getHeroes', [])) ); }
handleError()を作る
HeroService
の中に作るぞ、エラーを直接触る関数だ!- 汎用的な処理なので、型引数で取得できなかったデータの型を受け取るようにしよう
private handleError<T>(operation = 'operation', result?: T) { // Observable<Hero[]>を返す正常な関数を返す return (error: HttpErrorResponse): Observable<T> => { console.error(error); this.log(`${operation} failed: ${error.message}`); // 空のHero[]を返す return of(result as T); }; }
- consoleの取得結果は「HeroService: getHeroes failed: undefined 」となった
getHeroesをちょこっと改修
tap
オペレーターを使ってログ出力をまとめちゃおtap()
はpipe()
の中で使える、受け取った関数を実行するだけの関数.pipe()
の引数にtap()
とcatchError()
二つ入っていますが、順に処理してくれる。オペレーターは組み合わせて使うのだ!
getHeroes(): Observable<Hero[]> { const heroes = this.http.get<Hero[]>(this.heroesUrl).pipe( tap(() => this.log(`fetched heroes`)), // 戻り値のOperatorFunctionはObservable を返す関数 catchError( // エラー用にメッセージと空配列を渡す this.handleError<Hero[]>('getHeroes', []) ) ); return heroes; }
getHeroも同じく修正
http.get
時に自分のidの画面に渡れるようにしてあげればOK、他はだいたい同じ!- ちょっと待って!自分のidっていうけど…エンドポイントのURLにidは含まれていないのですが!!でも大丈夫、
:baseURL/:id
でidから取得する仕組みがあるみたい
const url = `${this.heroesUrl}/${id}`;
更新機能を追加する
いまだと、せっかく詳細画面で名前を変えてもGo backすると変更は元に戻ってしまう。変更を永続化するには、サーバーに送り返すべし!というわけで、保存ボタンを追加しよう
hero-detail.componentにsave()を作ろう
コンポーネント鉄の掟、「データの取得や保存は行わぬ」がありますので、ここもサービスを呼んで、保存されたら戻るコールバック関数にする
save() { this.heroService.updateHero(this.hero).subscribe(() => this.goBack()); }
サービスの中でupdate!
- http.put()を使う、こいつがサブスクされるとデータが書き換わるとな
- 引数には「URL」「アップデート用のデータ」「オプション(ヘッダ情報)」を設定する
- URLはidつけなくてOK、データから特定されるらしい、かしこいねえ
- これは「Angular in-memory-web-api」の機能で、一意のidがある前提だからみたい
- ヘッダ情報は新しく
new HttpHeaders
してContent-Type
のみ設定している。どんなデータで送信するか伝えるためにも必要
■ 感想
エラー周りの関数の理解がかなりむずかしかった。いや、全部難しいね、http周りの知識が乏しい!ゴールデンウイークは料理したりしてる、世界樹早くやりたい、と待ってる時間が一番楽しいカモネ
Angularチュートリアルをやる 5日目
■ 思ったこと
次の章に行くごとにわけわからん状態になってその都度勉強していく感じ、ほぼ世界樹の迷宮ですね
■ 5. ルーティングを使ったナビゲーションの追加
Angularルーターを使って画面遷移をやっていこう!
AppRoutingModule
- ルーティング専用のトップレベルモジュールっていうのがあると良い
- 慣例でモジュールのクラス名は
AppRoutingModule
となるよ! - モジュールは
ng generate module app-routing --flat --module=app
で作る--flat
:src/appに生成したファイルを置く---module=app
:AppModuleのimports配列に生成したモジュールを登録する(使うために登録は必須!)
- が、プロジェクト作成時に自動で作ってたみたいだ、もうあった!
routes
配列にHeroesComponent
のpathとコンポーネント名を設定、こうするとhttp://localhost:4200/heroes
が使えるようになる
RouterOutletを使う
AppRoutingModule
で設定したルーティングを設定するには、html上でrouter-outlet
タグを書いてあげればOK
routerLinkも使う
詳細にどこへ飛ぶか?は<nav>
要素の中にaタグ入れてrouterLink
を設定してあげるべし。routerLink
はこれでクリックをルーターのナビゲーションへ変換するセレクタだ。もうコンポーネントを直接書く必要はないぜ!
ダッシュボードビューを追加しよう
- 正直、ルーティングって複数ページnight意味ないし、も一個ぐらいコンポーネント増やしたいよね?おっしゃる通り、ということで
ng generate component dashboard
をしましょう - ダッシュボードビューではヒーロー配列からピックアップしてヒーローを表示する、なのでこちらのコンポーネントにも
heroService
を注入してgetHeroes()
を使おう!
デフォルトルート
空パスの場合に自動遷移させるにはAppRoutingModule routes
配列に{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
を追加するべし(今回はダッシュボードをデフォルト遷移先にするのだ)
詳細画面を遷移先に変えよう
- 今は
HeroesComponent
でヒーロー名クリックしたら下に出る感じですが…いろんなとこから遷移して表示する形に改修しよう heroes.component.html
のbutton
はrouterLink
に変更、リンク先はdetail
にhero.id
を足したものとする。idが2としたら、こんな感じになる!例)~/detail/2
- 選択したheroを元に
onSelect()
で詳細画面を表示する部分もいらなくなるよ - 当然、今のままではリンク先には飛べないが・・??
hero-detail.component.tsの大改修
~/detail/id
ありきで、idを取得し、そのデータをサービスからGETできるようにしましょう- そのためにもconstructorに以下を追加するノダ
ActivatedRoute
:ルートに関する便利機能を色々持ってるクラスHeroService
:おなじみ!サービスからデータをもらおうLocation
:ブラウザのURLをいい感じにやりとりするサービス、 今回は前のビューに戻るのに使う
constructor( private route: ActivatedRoute, private heroService: HeroService, private location: Location ) {}
- URLからidを取得するのに
route
が使えるぞ。route.snapshot
でコンポーネントが作成されたときのルート情報を取得しよう!スクショのURLはhttp://localhost:4200/detail/1
- ルートパラメータは文字列なので、Numberでキャストを忘れずに
- idが特定出来たらいつも通りサービスから取得すればOK
getHero() { const id = Number(this.route.snapshot.paramMap.get('id')); this.heroService.getHero(id).subscribe((hero) => (this.hero = hero)); }
- ちなみに、修正前は親コンポーネントからheroがバインディングされていたが…今の詳細コンポーネントは親から独立しているので
@Input hero?: Hero;
から@Input
は不要になる getHero()
はHeroService
がないのでこの時点ではエラーになるぞ、早急にHeroService.getHero()
を追加するのだ!
戻るボタンの追加
- 詳細画面からまえのがめんにもどれなくっちゃね、
hero-detail.component.html
に戻るボタンを追加しよう! - クリック時のイベントには
goBack()
を追加してhero-detail.component.ts
に実装しよう location.back()
を使えばよいです
■ 感想
くっついてるコンポーネントはなるべくマルっくとホドホドにホドいてイェ~そどってねツァク。
Angularチュートリアルをやる 4日目
■ 思ったこと
実生活がしんどすぎてきしめんで泣く!
■ 4. サービスの追加(2)
こっから難しいが、Promiseを乗り越えた今ならば!!
非同期処理にしてみよう
- 前回
heroService.getHeroes()
でヒーローを取得しましたが、これは同期的な処理ですので汎用的ではありません。非同期処理として実装してみるべし! - 最終的に
heroService.getHeroes()
したらObservable
が返ってくれば正解だ!Observable
はRxJSライブラリで重要なクラス、いや、何が何の何!?
RxJSライブラリとは
- 非同期処理を実装するためのライブラリ
- Observable型の実装を提供している
Observableってなによぉ・・!!
- RxJSの基本的なオブジェクトのことだっ!
- Observableした関数はConsumer(使う側?)がsubscribe(購読)するまでは実行されない
- サブスクするConsumerはその処理が完了orサブスク中止するまで状態の変化を通知として受け取れるらすぃ
- Observableによって公開された値をストリームと呼ぶ
- サブスクされる前に、ストリームを操作できるオペレーター関数がある
- 例)of()、map()、filter()、concat()、flatMap()
- サブスク自体は
subscribe()
で呼び出せマス
Observable HeroServiceにしてみよう
- Observableする関数はgetHeroes()、戻り値をObservable
型に書き換えるのだ - ストリームをそのままキャッチするには
of()
を使おう- ofはデータを特に加工せず、そのまま取得するオペレーター
- 戻り値は
Hero[]
からObservable<Hero[]>
となる
HeroesComponentでSubscribe!
- 戻り値が変わりましたので、getHeroesを使ってるコンポーネントも当然修正が必要になる
- Observableした関数が処理を終えるまで待ってあげられるようにしよう!
- 対象メソッドに
.subscribe()
をチェーンして、その中で引数を変数にセットできるコールバック関数を書いてあげればいーのだ
それはそうと、データ取得成功時にメッセージ出してみようぜ
- 例によって
ng generate component messages
でMessagesComponent を作成します app.component.html
で呼び出してあげれば準備はOK!- 次に、MessageService も
ng generate service message
作ったろう - message.service内にはmessages変数と
add()
とclear()
をrootで作成するのだ
サービス内でサービスを利用する
- 今作った
messageService
はHeroService
に注入する - 注入のやり方は覚えているか??コンストラクタに追加して引数に入れるだったね、サービスクラスでもおんなじ!
- おめでとう、
HeroService
内でmessageService
のメソッドおよび変数も使えるようになったぞ!
export class HeroService { // サービス内でサービスを利用する constructor(private messageService: MessageService) {} getHeroes(): Observable<Hero[]> { const heroes = of(HEROS); this.messageService.add('HeroService: fetched heroes'); return heroes; } }
HeroesComponentでもmessageServiceを利用する
- 同じく注入したげればOKなのよ
- クリック時に動く関数
onSelect
内でaddするようにしました。これでクリックした結果をメッセージ配列に貯めて画面に出せるようになったってワケ
■ 感想
ゴールデンウイークなのでどんどん進めたいですね・・・・
Angularチュートリアルをやる 3日目
■ 思ったこと
4年前ぐらいに買いっぱなしだった書籍「Angularアプリケーションプログラミング」を辞書のように使っていく!
【番外編】 Angularの概念
いまさらだが、やっぱこっからちゃんと見た方がいいよね(Angular 日本語ドキュメンテーション)
Angularとは
- HTMLとTypeScriptでSPA(=シングルページクライアントアプリケーション)を開発するためのフレームワーク
- 基本的な構成要素は、 NgModule で組織されたAngularコンポーネント・・NgModule ??
NgModule!?
@NgModule
デコレーターを付与されたクラスのこと- モジュールとは、Angularアプリを構成する部品(コンポーネント、サービス、ディレクティブ、パイプなど)をまとめた単位のこと
- Angularアプリは最低一個のモジュールが必要
- 起動時に呼ばれるのがルートモジュール(またはメインモジュール)
- とりあえずNgModule をインポートして
@NgModule
デコレーターで構成情報を付与すれば君も今日からモジュールだ!
Angularアプリケーションとは
- 常に1つの ルートモジュールと多くの 機能モジュール で構成されたもの!
デコレーター (@)
- Angularに構成情報を教えてあげるもの
- モジュール、コンポーネントやサービスなどのクラスに付与して使う
コンポーネント
- ページを構成するUI部品をまとめた単位のこと
- 起動時に呼ばれるのがルートコンポーネント(またはメインコンポーネント)
- Componentをインポートして
@Component
デコレーターで構成情報(紐づくビューとか)を付与すればよい - コンポーネントで使用したいデータはサービスから注入される
サービス
- コンポーネント間で共有したいデータやロジックを設定するクラス
- サービスクラスには
@Injectable()
デコレーターを付与して共有したいメソッドを定義する - これのいいところですが、コンポーネントがサービスクラスを実体化してインスタンス化…とかしなくても、サービスクラス使う宣言すればインスタンス化し放題なところです!
- そこら辺の仕組みはDIコンテナってやつがうまくやってくれている
- 依存関係(Dependency)の注入(injetion)なのでDI
■ 4. サービスの追加
今は配列にいろいろ直書きした仮データを表示しているが、この章ではモックサービスを利用していい感じにするらしい。
そもそもコンポーネント内では
データの取得や保存は行わぬ、コンポーネントはデータの受け渡しに専念せねばならぬのだ。なので、その他の処理はServiceクラスに任せよう!!
HeroServiceを作成しよう
ng generate service hero
ってやるとまたも良い感じにファイルが作成される。src/appの直下に出来るのがちょっとイヤ!今度はCREATE のみのようだ。
CREATE src/app/hero.service.spec.ts (347 bytes) CREATE src/app/hero.service.ts (133 bytes)
生成されたhero.service.ts
は@Injectable()
があらかじめ付与されていた、()の中に構成情報が書かれている。
デフォルトでprovidedIn: 'root'
となっているが、ここでは依存性の注入方法を宣言しており、ルート指定するとアプリケーション全体で使用できるみたい…むしろ、こうしないと使えないぜ!
データの取得
- データは例えばAPI、ローカルストレージ、モックデータなど色んなとこからやってくるが、サービスに取得ロジックを書いてあげればコンポーネントはただ受け取り屋さんになれるので便利!
- 今回は引き続きモックデータを使うので、
HEROES
をインポートし、取ってきた結果を入れるようの配列も必要なのでHero
もインポートする - あとはgetメソッドつくればOK!
getHeroes(): Hero[] { return HEROS; }
HeroesComponent の更新
- 上記の通りコンポーネントで直接データを取得する必要はないため、「2. リストの表示>ヒーローのモックを作成」で作ったモッククラスのインポートは削除する
- そんで、今作ったサービスをインポートする!
- Heroクラスはインポート済なので、もらったデータを
heroes
に設定できるように書き換える - このままではサービスはまだ使えない、サービスの注入を行おう
- コンストラクタを追加して、引数に
HeroService
を渡してあげればOK
constructor(private heroService: HeroService) {}
HeroesComponentでデータをゲット
- するには、注入されたサービスのgetメソッドを使いましょう
// サービスからheroesを取得 getHeros() { this.heroes = this.heroService.getHeroes(); }
- getメソッドはngOnInit()というメソッドで呼び出して使う、コンストラクタは使わないのか?オーキドのことば、ものにはつかいどころがあるんじゃ…!
ngOnInit()
ngOnInit(){ this.getHeros(); }
- ここまでやれば、画面が動く!
いったん整理
■ 感想
DI完全に理解した!!
Angularチュートリアルをやる 2日目
■ 思ったこと
バインドって聞くとサバクのネズミ団を思い出す!ということでチュートリアル続き
2. リストの表示
ヒーローのモックを作成
反復ディレクティブ
- for文的なやつ、
*ngFor
をタグに埋め込むとそいつが繰り返して表示される - ディレクティブはhtml内で使えるカスタム属性
<li *ngFor="let hero of heroes">
ディレクティブもうちょっと詳しく
*ngIf
、*ngFor
など要素を増やしたり減らすのは構造ディレクティブ- 頭の
*
は=構造ディレクティブの解釈でOK 、実際は短縮表記…らしい
- 頭の
ngModel
など要素やコンポーネントの見た目や動作を変えるのが属性ディレクティブ- コンポーネントもディレクティブだが、コンポーネントはコンポーネント
クリックイベントもバインディング!
- 今リストをボタンで作成してるんだけど、それらのクリックイベントを作ろうという話
- これはイベントバインディングを使いますね間違いない…ということで、htmlのbuttonに
(event) = "handler"
構文を埋め込むノダ
<button [class.selected]="hero === selectedHero" type="button" (click)="onSelect(hero)" >
- handlerはts側に作成しよう
selectedHero?: Hero; // 送られてきたheroをselectedHeroに格納 onSelect(hero: Hero): void { this.selectedHero = hero; }
ngIfで詳細を出してみる
- せっかくクリックしたヒーローを取得できるようになったので、使ってみよう
- 今回は
<div *ngIf="selectedHero"><div>
で、selectedHeroが取得されてるときのみヒーローの詳細を表示するよーにした- 要するにクリックされたときってこったね!
クリックされたボタンを分かりやすくする
- ボタンがクリックされた時だけCSSを追加してあげればよい
[class.selected]="hero === selectedHero"
でtrueの時だけCSSにselected
のCSSが追加されマス、YES属性バインディング!
.heroes button:selected{ background-color: #505050; color: white; }
3. フィーチャーコンポーネントの作成
てな感じで今は一覧と詳細が一個のコンポーネントに書かれている感じだが、、こんなん分割するに越したことがないぜ!
ということでまずはng generate component hero-detail
で新たなコンポーネントを作りました。例によって@NgModuleに追記も増えていた。確かに実行時のログ見たらUPDATE されてあったわ
CREATE src/app/hero-detail/hero-detail.component.html (26 bytes) CREATE src/app/hero-detail/hero-detail.component.spec.ts (628 bytes) CREATE src/app/hero-detail/hero-detail.component.ts (221 bytes) CREATE src/app/hero-detail/hero-detail.component.css (0 bytes) UPDATE src/app/app.module.ts (607 bytes)
htmlの分割
heroes.component.html
からhero-detail.component.html
に詳細部分を持ってきました- もとは
*ngIf="selectedHero"
だったけど、詳細コンポーネントは受け取ったheroをただ表示すればいーので<div *ngIf="hero">
に書き換える - しかし、Hero型がtsファイルにインポートされてないからエラー出るぞ!次!
子コンポーネントで@Input()
hero-detail.component.ts
は外部からデータを受け取る身、子コンポーネントだったのだ- それゆえ、ただHero型をインポートすればいいだけではなかった。データ受け取ります!宣言しなきゃいけないらしい
- というわけなので、heroを使いたいなら、
@Input() hero?: Hero
と書こう
親コンポーネントはhtmlで プロパティバインディング
- こういうことだ!
<!-- HeroesComponent.selectedHero → ターゲット要素.hero への単方向データバインディング --> <app-hero-detail [hero]="selectedHero"></app-hero-detail>
■ 感想
専門用語が難しいのでその都度調べてやるしかない!次の章から一気にレベルアップする気がするぜ!
Angularチュートリアルをやる 1日目
■ 思ったこと
まずは公式みながら環境設定→ワークスペースの作成→チュートリアルまでやろうと思うhttps://angular.jp/guide/setup-local#angular-cliをインストールする-
■ Angularをはじめよう
下準備
なになに、ローカルシステムにAngularをインストールするには、Node.js
とnpm
が使える必要とな……ある!!OK!!
Angular CLIをインストール
Angular開発で必須なコマンドラインツールのこと、コマンドプロンプトでnpm install -g @angular/cli
でインストールできる、ng version
でversion確認まで出来たらOK!ng なんちゃら
って感じで使えるよ
ワークスペース作ってみる
VSCodeのターミナルでng new my-app
しました。全部入りのひな形プロジェクトが作られるみたい、npmインストールも兼ねている。成功するとこんな感じ
実行してみる
cd my-app
してng serve --open
するとhttp://localhost:4200/
が立ち上がって画面が開く!これでとりあえずの動作確認はいいか
■ チュートリアルやり申す
https://angular.jp/tutorial/tour-of-heroes/toh-pt0ツアー・オブ・ヒーローズ……?
1. ヒーローエディター
アプリケーションシェル
画面開いた時に表示されたページ、それがアプリケーションシェルらしい。こいつはAppComponentと名の付く三つのコンポーネントから成り立つぞ、src/app
に行ってみよお!
コンポーネントを作る
ng generate component heroes
ってやると、src/app/heroes/
ごとまるっとコンポーネントが作成される!こりゃあ便利だね。中身はやっぱりtsとhtml,css
Componentシンボル
- 生成したtsファイルにはデフォルトでComponentがインポートされていたが、クラスに
@Component
もくっついているはず - こいつはデコレーターつって、クラスにメタデータを付与してくれていたのだ
- (メタデータはとりあえず、クラスに設定必要な情報と理解しておこう)
- ng generateが生成してくれたものは3つのメタデータプロパティでした
- こうしてみると、確かに自動生成されているとありがたい
インターフェースを作成する
- おさらいすると、インターフェースはオブジェクト型に型名つけるやつ!
- heroesクラスにこれからHeroを生成していくわけだけど…
src/app
に自分でhero.ts
作って、そこにHeroインターフェースを作成しとこうって話 - 作ったオブジェクトはhtml内に
{{selector.プロパティ名}}
でバインディングすべし
双方向データバインディング
<input id="hero-name" [(ngModel)]="hero.name" placeholder="name" />
placeholder
はhtmlで使える属性、初期値を設定できるぜ
ていうか…データバインディングについてもっと詳しく!
- コンポーネントとテンプレート(ビュー)を紐づけるための仕組み
- データの流れによっていろいろ書き方がある
AppModule
- ngModelを使うには
FormsModule
のインポートが必要 - インポート先は
AppModule
!Angular全体としてどーいう部品使う?みんなファイルやライブラリ何使ってるの?…いわゆるメタデータ!こゆのを知っておく場所 - だいたいメタデータは
@Component
で個別に付与されてるけど、その他重要なものはAppModuleの@NgModule
に含まれている - ということで、ここにインポートして
@NgModule
のimports配列
に追記してあげればOK- アプリケーションに必要な外部モジュールのリストだよ
- これに限らず、すべてのコンポーネントは
NgModule
で宣言されていなければならない - 実際、さっき作ったHeroesComponentもいつの間に
declarations
配列に含まれているng generate
したときに自動で書きこんでくれてたんだね…!ありがとう、CLI
■ 感想
手でコンポーネント作ったらそれなりに事故が起きそうだ、ありがとうCLI。チュートリアルの文章がユーモアあって結構おもしろい、いいね!!でも、細かい仕組みとかはよくわからんので・・まずは手を動かして、そのあと改めて勉強も必要そうな!
プロを目指す人のためのTypeScript入門 読書メモ⑭ 第8章(3)
■ 思ったこと
早くAngularのチュートリアルやりたいぜ…
■ 第8章 非同期処理(8.4~8.5.4)
- 前回まではthenで処理を動かしていたが、実際はもっと使われる書き方があるらしい
ちょっとおさらい
- Promise
みたいに書くけど、Promiseオブジェクトってどういうもんなの - なんも入ってなければこんな感じ
Promise { <pending> }
- 例のようにnumber入れたらこんな感じで返ってくるよ
Promise { 100 }
- だから型引数が必須なのですね!
async関数
- functionの前にasyncをつける
async function
構文から始まるぞ - アローで書くなら
const main = async () => { 処理 }
って感じ - 返り値は必ずPromise!だから中身を使いたいなら
返り値.then()
- こんな感じで使える
const result = 返り値.then((変数) => {なんか処理})
- こんな感じで使える
await式
- async関数の中で使える構文!
await
を使うとasync関数の実行が一時中断する- awaitがくっつく式はPromiseオブジェクト、Promiseの結果が出るまで待ってくれるのさ
// await実行されたら解決するまで中断する async function getNumber() { try { console.log(`getNumber staert`); await sleep(1000); console.log(`getNumber end`); return 30; } catch { console.log(`失敗!`); } } console.log(`実行!`); getNumber().then((num) => { console.log(`getしたNumberは${num}`); }); // awaitを待ってる間外の関数は普通に進む console.log(`待機中~`); //[console] // 実行! // getNumber staert // 待機中~ // getNumber end // getしたNumberは30
■ 感想
難しいが、だいたいは、、前よりはOK!後輩に説明できるかというと、、??!次の9章はコンパイラオプションはさらっと読んだので、またプロジェクト1から作るときに熟読します!ということでここで一区切り!!基本的なことが学べたというか、TypeScriptに慣れることができたって感じ!!土台作りとしてほんとにわかりやすかった!!!ありがとうございます!!!!