[解決済み] angularでObservable/http/asyncの呼び出しから応答を返すにはどうすればよいですか?
質問
サーバーにhttpリクエストを行い、データを取得するobservableを返すサービスがあります。このデータを使用したいのですが、いつも
undefined
. 何が問題なのでしょうか?
サービス :
@Injectable()
export class EventService {
constructor(private http: Http) { }
getEventList(): Observable<any>{
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get("http://localhost:9999/events/get", options)
.map((res)=> res.json())
.catch((err)=> err)
}
}
コンポーネントです。
@Component({...})
export class EventComponent {
myEvents: any;
constructor( private es: EventService ) { }
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
});
console.log(this.myEvents); //This prints undefined!
}
}
私が調べたのは 非同期呼び出しからレスポンスを返すにはどうすればよいですか? を投稿しましたが、解決策は見つかりませんでした。
どのように解決するのですか?
理由は?
という理由は
undefined
になっているのは、非同期な操作をしているからです。つまり、この操作を行うには
getEventList
メソッドを完了させるのに時間がかかるということです (主にネットワークの速度に依存します)。
それでは、httpの呼び出しを見てみましょう。
this.es.getEventList()
で実際にhttpリクエストを行った("fire")後、そのリクエストに対応するように
subscribe
を使うと
を待ちます。
を待つことになります。待っている間、javascriptはこのコードの下の行を実行し、もし同期的な割り当てや操作に遭遇したら、すぐにそれを実行することになります。
つまり
getEventList()
を購読し、レスポンスを待ちます。
console.log(this.myEvents);
の行はすぐに実行されます。そして、その値は
undefined
のように、サーバから応答が来る前に(あるいは、そもそも初期化したものに対して)実行されます。
するのと似ています。
ngOnInit(){
setTimeout(()=>{
this.myEvents = response;
}, 5000);
console.log(this.myEvents); //This prints undefined!
}
解答です。
<ブロッククオート
では、この問題をどのように克服すればよいのでしょうか。コールバック関数を使用します。
subscribe
メソッドを使用します。なぜなら、サーバーからデータが届くと、それは
subscribe
の中に入って、レスポンスと一緒に表示されるからです。
ということで、コードを変更すると
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //<-- not undefined anymore
});
は、しばらくしてからレスポンスを表示します。
どうすればいいのでしょう。
単にログを取るだけでなく、レスポンスに対して行うべきことがたくさんあるかもしれません。これらの操作はすべてコールバックの内部で行う必要があります (コールバックの内部の
subscribe
関数の中)で、データが到着したときに行います。
もう一つ挙げるとすれば、もしあなたが
Promise
の背景を持つ場合、その
then
コールバックは
subscribe
に対応します。
やってはいけないこと
非同期操作を同期操作に変更しようとしてはいけません (できるわけではありませんが)。非同期オペレーションがある理由の 1 つは、ユーザーがその時間内に他のことができるのに、オペレーションが完了するのを待たせないようにするためです。非同期操作の1つが完了するのに3分かかるとします。もし非同期操作がなかったら、インターフェースは3分間フリーズしてしまうでしょう。
お勧めの読み物です。
この回答のオリジナルクレジットは、次のとおりです。 非同期呼び出しから応答を返すにはどうすればよいですか?
しかし、angular2のリリースでtypescriptとobservablesが導入されたので、この回答はobservablesで非同期リクエストを処理するための基本をカバーすることを願っています。
関連
-
[解決済み】「GET」パラメータから値を取得する(JavaScript)【重複】。
-
[解決済み] JavaScript で範囲を作成する - 奇妙な構文
-
[解決済み] Node.jsでbase64エンコードされた画像をAmazon S3へアップロードする
-
[解決済み] JavaScriptで、ある文字列が別の文字列の中に出現するすべてのインデックスを見つけるにはどうすればよいですか?
-
[解決済み] WebStormで未解決の変数が大量にある場合の警告に対処する方法は?
-
[解決済み] JavaScriptを使用してHTML要素に属性を追加/更新するには?
-
[解決済み] Javascript / jQueryでAndroid端末を検出する。
-
[解決済み] 文字列とラベルのローカライズとグローバリゼーションのベストプラクティス【終了しました
-
[解決済み] JavaScript で css プロパティを使用して HTML 要素の背景色を設定する方法
-
[解決済み] ReduxとRxJS、似ているところはありますか?[クローズド]
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] ジェスト あるクラスの特定のメソッドをモックする方法
-
[解決済み] 配列からオブジェクトを生成する
-
[解決済み] モバイルWeb HTML5フレームワークの選び方【終了しました
-
[解決済み] WebStormで未解決の変数が大量にある場合の警告に対処する方法は?
-
[解決済み] オブジェクトの配列からReactコンポーネントをレンダリングする
-
[解決済み] サブドメインにまたがってlocalStorageを使用する
-
[解決済み] react-routerのハッシュフラグメントからクエリパラメータを取得する
-
[解決済み] イテレータでmap()を使用する
-
[解決済み] Node.jsのES6クラスをrequireで作る
-
[解決済み] JavaScript で `throw` の後に `return` をする必要がありますか?