一定の間隔でコンポーネントページのデータを更新する必要があります。また、何らかのアクションを実行した後、データを更新する必要があります。応答の準備ができたときにサブスクライブできるように、サービスでObeservablesを使用しています。サブスクリプションをオブジェクトにプッシュして、ngDestroy
でそれをクリアできるように、同じことを達成するために次の方法があると思います。
方法1:setInterval
ngOnInit
に間隔を設定しました。これにより、等間隔でrefreshDataが呼び出されます。間隔オブジェクトは、clearInterval
メソッドのngOnDestroy
を使用してクリアされます。
export class MyComponent implements OnInit, OnDestroy {
private subscription: Subscription = new Subscription();
data: any;
interval: any;
ngOnInit() {
this.refreshData();
this.interval = setInterval(() => {
this.refreshData();
}, 5000);
}
ngOnDestroy() {
this.subscription.unsubscribe();
clearInterval(this.interval);
}
refreshData(){
this.subscription.add(
this.myService.getData()
.subscribe(data => {
this.data = data;
})
);
}
doAction(){
this.subscription.add(
this.myService.doAction()
.subscribe(result => {
if(result === true){
this.refreshData();
}
})
);
}
}
Q1:更新呼び出しごとに、サブスクリプションがsubscription
オブジェクトに追加されます。これにより、メモリ使用量が増加し、ユーザーがしばらくページを開いたままにするとブラウザーがクラッシュする可能性がありますか?
方法2:Observable.timer
このメソッドは、データが更新された後に作成されるタイマーを使用しています。
export class MyComponent implements OnInit, OnDestroy {
private subscription: Subscription = new Subscription();
data: any;
ngOnInit() {
this.refreshData();
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
refreshData(){
this.subscription.add(
this.myService.getData()
.subscribe(data => {
this.data = data;
this.subscribeToData();
})
);
}
subscribeToData(){
this.subscription.add(
Observable.timer(10000).subscribe(() => this.refreshData())
);
}
doAction(){
this.subscription.add(
this.myService.doAction()
.subscribe(result => {
if(result === true){
this.refreshData();
}
})
);
}
}
Q2:同じ質問(Q1)があります。これにより、サブスクリプションオブジェクトにもタイマーが追加されるため、サブスクリプションオブジェクトのサブスクリプションが事実上2倍になります。
Q3:アクションメソッド-doAction()の後にデータを更新するには、refreshDataが呼び出されます。それでタイマーの別のチェーンが作成されますか?
Q4:メモリリークのない、または他の方法がある場合、どちらが良い方法ですか?
問題なくこれを実行できるはずです。
ngOnInit() {
this.refreshData();
this.interval = setInterval(() => {
this.refreshData();
}, 5000);
}
refreshData(){
this.myService.getData()
.subscribe(data => {
this.data = data;
})
);
}
この投稿 Angularに従って、それ自体のクリーンアップを処理します。
ただし、、アプリでライブデータストリームを使用する場合は、次の各応答にサブスクライブするのではなく、コンポーネントを変更することをお勧めしますサービスのhttpリクエストの場合、代わりにコンポーネントのngOnInit()
でサービスの新しいobservable data$
プロパティに一度サブスクライブします。次に、間隔で(あなたがしているように)サービスでupdateData()
を呼び出します(または間隔をサービス内で設定します)が、サブスクライブしないでください。サービスがデータを正常に取得すると、次の値をその監視可能なdata$
プロパティにプッシュし、アプリ内の任意の場所に対応できるサービスからのデータストリームを提供します。
ngOnInit() {
this.myService.data$.subscribe(data => { // subscribe once to the data stream
this.data = data;
})
this.refreshData();
this.interval = setInterval(() => {
this.refreshData();
}, 5000);
}
refreshData(){
this.myService.updateData(); // simply signal for the service to update its data stream
}
myService.data$
が、サービスで更新される観察可能なBehaviourSubjectである場合、次のようになります。
public data$: BehaviorSubject<any> = new BehaviorSubject({});
updateData() {
let data = this.http.get('http://www.data.com').map((data)=>{
return data.json();
}).do((data)=>{
this.data$.next(data);
})
}
これにより、複数のサブスクリプションを回避し、それを必要とするすべてのコンポーネントでデータストリームを利用できるようにすることができます。
@SpaceFozzyの回答を少し拡張して、将来の訪問者の役に立つようにしています。データを更新するには、@ SpaceFozzyの方法を使用しました。しかし、サブスクリプションについては、より良いアプローチを得ました。答えをご覧ください- https://stackoverflow.com/a/4117716 。そこで、サービスとコンポーネントを次のように更新しました。お役に立てれば。
私のコンポーネント
import { Subject } from 'rxjs/Subject';
export class MyComponent implements OnInit, OnDestroy {
private unsubscribe: Subject = new Subject();
data: any;
interval: any;
ngOnInit() {
this.refreshData();
if(this.interval){
clearInterval(this.interval);
}
this.interval = setInterval(() => {
this.refreshData();
}, 10000);
this.myService.data$.takeUntil(this.unsubscribe)
.subscribe(data => {
this.data = data;
});
}
ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
refreshData(){
this.myService.updateData()
.takeUntil(this.unsubscribe)
.subscribe();
}
doAction(){
this.subscription.add(
this.myService.doAction()
.subscribe(result => {
if(result === true){
this.refreshData();
}
})
);
}
}
私のサービス
import { Observable, BehaviorSubject } from 'rxjs';
@Injectable()
export class MyService {
private dataSubject: BehaviorSubject<YourDataModel[]> = new BehaviorSubject([]);
data$: Observable<YourDataModel[]> = this.dataSubject.asObservable();
updateData(): Observable<any> {
return this.getData().do((data) => {
this.dataSubject.next(data);
});
}
// My data is an array of model objects
getData(): Observable<YourDataModel[]>{
return this.http.get('/path')
.map((response: Response) => {
let data = response.json() && response.json().your_data_objects;
if(data){
return data;
}
})
}
}