Angle2でオブザーバブルとサブスクリプションの周りに頭を包み込むのに本当に苦労しています。私が現在抱えている問題は次のとおりです。
APIからデータを送信および取得するメソッドを含むサービスがあります。サービスはコンポーネントに注入され、コンポーネントはサービス内のこれらのメソッドを直接呼び出します。その後、サービスはデータを取得して保存しますが、そのデータをコンポーネント内で処理したいと思います。サービスがデータ自体を取得して保存した後に、コンポーネントに関数を実行させる方法を見つけることはできません。
service.ts
import { Injectable } from 'angular2/core';
import { Http } from 'angular2/router';
@Injectable()
export class Service {
result: Object;
constructor(http: Http) {
this.http = http;
}
httpGet(url) {
return this.http.get(url).subscribe(
result => this.result = result.json(),
error => console.log(error),
() => {}
)
}
}
component.ts
import { Component } from 'angular2/core';
import { Service } from './service';
@Component({
...
})
export class Component {
formattedResult: Object;
constructor(service: Service) {
this.service = service;
this.service.httpGet('/api')
// How do I call format result on service.result only after it is completed?
this.formatResult(service.result) // Need to execute this after the http call is completed
// I want something like:
this.service.httpGet('/api').then(() => formatResult(this.service.result));
}
formatResult(result) {
this.formattedResult = result.map(x => x.length) // For example
}
}
私自身の質問に答えるには:
アプリのルートで、Rxjsをインポートします。
import 'rxjs/Rx';
これにより、Angularに含まれる「Observable-lite」だけでなく、完全なObservableオブジェクトにアクセスできます。これにより、Http要求を.map .reduceなどすることができます。
結果にサブスクライブするコンポーネントであっても、Httpリクエストで.mapを使用して、サービスのコンテキストで任意のコードを実行できるようになりました。ですから、最初にやろうとしていたことを達成するために、次のことができます。
service.ts
import { Injectable } from 'angular2/core';
import { Http } from 'angular2/router';
@Injectable()
export class Service {
result: Object;
constructor(http: Http) {
this.http = http;
}
httpGet(url) {
return this.http.get(url).map(
result => {
let data = result.json();
this.result = data;
return data
}
)
}
}
component.ts
import { Component } from 'angular2/core';
import { Service } from './service';
@Component({
// Component setup
})
export class Component {
formattedResult: Object;
constructor(service: Service) {
this.service = service;
this.service.httpGet('/api').subscribe(
data => this.formatResult(data);
);
}
formatResult(result) {
this.formattedResult = result.map(x => x.length) // For example
}
}
返信のGunterとMarkに感謝します。これで頭を抱えることができ、Observablesがこの問題を解決する多くのドキュメントを経験したことを理解できたと思います。
結果が既に到着しているかどうかを確認し、そうであれば、新しいプロミスを作成し、結果ではなく、結果で完了し、フェッチして、プロミスとして返します。
@Injectable()
export class Service {
result: Object;
constructor(http: Http) {
this.http = http;
}
httpGet(url) {
if(result === undefined) {
return this.http.get(url).toPromise().then(
result => this.result = result.json(),
error => console.log(error);
);
} else {
return new Promise().resolve(result);
}
}
}
TSがわからないため、このコードにエラーが含まれている可能性があります(Angular Dartのみを使用)。
こちらもご覧ください
- http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
これは、Rxjsメソッドで簡単に発生する可能性があります。ここでは、アプリケーションをロードした後にサービスを呼び出して、複数のコンポーネントにサブスクライブすることができるシンプルで古典的な方法を示します。サービスがすべてのコンポーネントで再利用可能であることを確認してください。そのため、uがサービスおよびマップでコードを実行できるように、コンポーネントでのみサブスクライブします。
サービス:
import { Injectable } from 'angular2/core';
import { Http } from 'angular2/http';
@Injectable()
export class Service {
result: Object;
constructor(private http: Http) {}
private _urlGet = '/api';
httpGet(){
return this.http.get(this._urlGet)
.map(res => JSON.parse(res.json()))
.do(result => {
this.result = result;
}, error => console.log(error))
}
}
コンポーネント
export class Component {
formattedResult: Object;
constructor(private service: Service) { }
ngOnInit(){
this.service.httpGet().subscribe(result => {
this.formattedResult = result;
}
}
}
その場合、コールバック関数を使用できますが、
例として、これがサービスモジュールでポストサービスをトリガーするポスト関数であると考えてください。
_postData(id: string, name: string) {
console.log("Got you",id);
this._employeeService.postServices({id: id, name: name})
.subscribe(
(response:Response) => this.consoleMyOutput(),
error => console.log(error)
);
}
_
ここで、関数consoleMyOutput()
に注意してください。これは、サービスが呼び出された後に応答が取得されるとトリガーされます
さて、
_consoleMyOutput(){console.log("Write Your call back function")};
_
この機能はその直後にトリガーされます。