🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

AngularJS

AngularJSはオープンソースのJavaScriptフレームワークです。ブラウザ上で動作するウェブアプリケーションの開発にMVCアーキテクチャを取り入れることを目的としています。

Q&A

2回答

9606閲覧

Angularで非同期処理によって取得した値が格納されるのを待ってから、後続の処理を実行したい

rakiiiii

総合スコア1

Angular

Angularは、JavaScriptフレームワークです。AngularJSの後継であり、TypeScriptベースで実装されています。機能ごとに実装を分けやすく、コードの見通しが良いコンポーネント指向です。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

AngularJS

AngularJSはオープンソースのJavaScriptフレームワークです。ブラウザ上で動作するウェブアプリケーションの開発にMVCアーキテクチャを取り入れることを目的としています。

0グッド

0クリップ

投稿2021/01/10 13:50

###前提
AngularでWebアプリを開発している中での質問です。(超初心者です。)

test.component.tsではAngularのHttpClientを利用して
外部ネットワークに格納されているpageSize配列の0番目を取得し、
TestService側で宣言した"res"に格納しています。(TestService.tsのparamsGetPageSize)

その後、test.component.tsで取得したpageSize配列の0番目が格納された"res"を
TestService.tsのparamsGet関数で利用します。

###意図
TestService.tsのコードを見ていただければ分かる通り、
paramsGetPageSizeとParamsGetは
postParam = postParam.set('pageSize', ***);の***部分が固定値か、変数か以外に違いはありません。
pageSizeのような環境変数は外部に置いておき、それを読み込むようにしたいという意図があり、
pageSizeを読み込むための関数は固定値(仕方なし)、それ以外でparamsGet関数を利用する場合は、
取得した変数を用いる、という処理にしています。

このparamsGet関数は様々な場面で利用されます。

###質問
非同期なのが原因かと思いますが、test.component.tsで取得したpageSizeがresに格納される前に
TestService.tsのparamsGetが実行されてしまうため、resがundefinedのまま処理が進んでしまいます。

paramsGetが実行されるとき、resがundefinedの場合は値が格納されるのを待って処理を開始する、という方法があればご教授いただけないでしょうか。

よろしくお願いいたします。

###urlEncoder.ts

TypeScript

1import { HttpParameterCodec } from '@angular/common/http'; 2 3export class UrlEncoder implements HttpParameterCodec { 4 encodeKey(key: string): string { 5 return encodeURIComponent(key); 6 } 7}

###TestService.ts

TypeScript

1 2import { HttpClient, HttpParams } from '@angular/common/http'; 3import { UrlEncoder } from 'urlEncoder.tsのパス'; 4 5export class TestService{ 6 // test.component.tsから取得できるように宣言 7 public res = ""; 8 constructor(private http: HttpClient) { } 9 10 private setRequestParams(): HttpParams{ 11 let httpParams: HttpParams = new HttpParams({ encoder: new CustomURLEncoder() }); 12 httpParams = httpParams.set('hoge', '1'); //http://-----&hoge=1 になります。 13 } 14 15 paramsGetPageSize(path: string, postParams: any = {}): Observable<any> { 16 let postParam: HttpParams = this.setRequestParams(); 17 18 // 固定値を使用 19 postParam = postParam.set('pageSize', '100'); 20 return this.http.get(path, { params: postParam }); 21 } 22 23 paramsGet(path: string, postParams: any = {}): Observable<any> { 24 let postParam: HttpParams = this.setRequestParams(); 25 26 // test.component.tsで取得したthis.resを利用 27 postParam = postParam.set('pageSize', this.res); 28 return this.http.get(path, { params: postParam }); 29 } 30};

###test.component.ts

TypeScript

1import TestService from {'Service.tsのパス'}; 2 3@component{ 45} 6 7export class TestComponent implements OnInit{ 8 constructor( 9 private test: TestService, 10 ) 11 12 ngOnInit(){ 13 this.test.paramsGet('http://------').subscribe(res => { 14 this.response = res.pageSize[0] //外部インターネット上のpageSize配列の0番目を取得 15 // サービスのプロパティに代入 16 this.test.res = this.response; 17 } ); 18 19 this.test.paramsGet('*******').subscribe( 20 処理 21 ); 22 } 23 24}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ngOnInit(){ this.test.paramsGet('http://------').pipe( tap((res) => { this.response = res.pageSize[0] this.test.res = this.response; }), mergeMap(() => this.test.paramsGet('*******').pipe( tap(() => { 処理 }) )) ).subscribe() }

お察しの通りObservableの処理は非同期のため、二つのObservableをsubscribeした場合、並列に実行されます。
回避するためには、RxJSのmergeMap(またはswitchMapでも可)パイプを用いて、直列実行されるようにしてあげます。

従来subscribeの中で行っていた処理は、tapパイプの中で行うことができます。

投稿2021/01/29 00:57

kaito3desuyo

総合スコア143

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こういう書き方もできます。

ts

1 async ngOnInit(){ 2 // awaitで待たせるためにPromise化させる 3 await this.test.paramsGet('http://------').toPromise().then(res => { 4 this.response = res.pageSize[0] //外部インターネット上のpageSize配列の0番目を取得 5 // サービスのプロパティに代入 6 this.test.res = this.response; 7 } ); 8 9 this.test.paramsGet('*******').subscribe( 10 処理 11 ); 12 }

ですが、kaito3desuyoさんの回答の方が拡張性(エラー処理の追加)などに優れています
私の書き方はあくまで「こういう書き方があるんだなー」ぐらいの知見程度にした方がよいかと。

投稿2021/01/29 17:45

mosapride

総合スコア1480

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問