2016-06-28 16 views
12

Mam usług i składnik, który używa go:ObjectUnsubscribedError próbując zapobiec subskrypcji dwukrotnie

  • PagesService
  • PagesListComponent

W PagesService mam tablicę Pages. Powiadomienia o zmianach w tablicy za pośrednictwem BehaviorSubject, które są subskrybowane.

Urządzenia PagesService są dostępne pod adresem , aby udostępnić tylko jedną instancję. To dlatego, że muszę przechowywać tablicę, zamiast pobierać strony za każdym razem, gdy są potrzebne.

Kod jest następujący:

pages.service.ts

import { Injectable } from '@angular/core'; 
import { BehaviorSubject } from 'rxjs/Rx'; 
import { Http, Response } from '@angular/http'; 

import { Page } from './../models/page'; 

@Injectable() export class PagesService { 

    public pages$: BehaviorSubject<Page[]> = new BehaviorSubject<Page[]>([]); 
    private pages: Page[] = []; 

    constructor(private http: Http) { } 

    getPagesListener() { 
     return this.pages$; 
    } 
    getAll() { 
     this.http.get('/mockups/pages.json').map((res: Response) => res.json()).subscribe(
      res => { this.resetPagesFromJson(res); }, 
      err => { console.log('Pages could not be fetched'); } 
     ); 
    } 

    private resetPagesFromJson(pagesArr: Array<any>) { 
     // Parses de Array<any> and creates an Array<Page> 
     this.pages$.next(this.pages); 
    } 
} 

pages_list.component.ts

import { Component, OnInit } from '@angular/core'; 
import { Router } from '@angular/router-deprecated'; 
import { BehaviorSubject } from 'rxjs/Rx'; 

import { PagesService } from '../../shared/services/pages.service'; 
import { GoPage } from '../../shared/models/page'; 

@Component({ 
    moduleId: module.id, 
    selector: 'go-pages-list', 
    templateUrl: 'pages_list.component.html', 
    styleUrls: ['pages_list.component.css'] 
}) 
export class PagesListComponent implements OnInit { 
    pages$: BehaviorSubject<GoPage[]>; 
    pages: GoPage[]; 
    constructor(private pagesService: PagesService, private router: Router) { } 

    ngOnInit() { 
     this.pages$ = this.pagesService.getPagesListener(); 
     this.pages$.subscribe((pages) => { this.pages = pages; console.log(pages) }); 
     this.pagesService.getAll(); 
    } 
    ngOnDestroy() { 
     this.pages$.unsubscribe(); 
    } 
} 

Działa to dobrze za pierwszym razem, zarówno subskrypcja onInit i de unsubscription onDestroy. Ale kiedy wrócę do listy i spróbuję ponownie zasubskrybować (aby pobrać aktualną wartość stron [] i nasłuchiwać przyszłych zmian), to odpala błądEXCEPTION: ObjectUnsubscribedError.

Jeśli nie anuluję subskrypcji, za każdym razem, gdy wejdę na listę, nowa subskrypcja zostanie ułożona w stos, a wszystkie zostaną uruchomione po odebraniu następnego().

Odpowiedz

30

chciałbym uzyskać subskrypcji i wypisać na to w ten sposób, a nie w tej sprawie bezpośrednio:

ngOnInit() { 
    this.pages$ = this.pagesService.getPagesListener(); 
    this.subscription = this.pages$.subscribe((pages) => { // <------- 
    this.pages = pages; console.log(pages); 
    }); 
    this.pagesService.getAll(); 
} 

ngOnDestroy() { 
    this.subscription.unsubscribe(); // <------- 
} 
+3

czy możesz wspomnieć, dlaczego nie zadziałało bezpośrednio wywoływanie rezygnacji z wstrzykiwania referencji podmiotu? –

5

.subscribe() zwraca Subskrypcja

  • należy użyć tego zrezygnować


np. Rodzic ma reloadSubject: Subject;

  • child1 -> prenumeruje
  • child2 -> prenumeruje

child1 - "działa" -> wypisać za jego subskrypcji

ngOnInit{ 
    sub: Subscription = parent.subscribe(); 
} 
onDestroy{ 
    this.sub.unsubscribe(); 
} 


child2 - "nie działa" - > anuluj subskrypcję dla całego rodzica

ngOnInit{ 
    parent.subscribe(); 
} 

onDestroy{ 
    parent.unsubscribe(); 
} 

Jeśli zadzwonisz, aby anulować subskrypcję na rodzica, oba dzieci zniknęły.
Jeśli zrezygnujesz z subskrypcji, którą otrzymasz z domeny.subscribe() to wtedy tylko jedno dziecko jest anulowane.

Proszę mnie poprawić, jeśli się mylę!

Powiązane problemy