尝试阻止两次订阅时出现ObjectUnsubscribed

Alv*_*ste 35 rxjs typescript rxjs5 angular

我有一个服务和一个使用它的组件:

  • PagesService
  • PagesListComponent

PagesService我有一个数组Pages.我通过BehaviorSubject订阅它们的数据来通知数组中的更改.

PagesService在提供bootstrap,到只有一个实例共享.那是因为我需要保留数组,而不是每次需要时都下载页面.

代码如下:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

这第一次工作正常,订阅onInit和de unsubscription onDestroy.但是当我返回列表并尝试再次订阅(获取pages []的当前值并监听将来的更改)时,它会触发错误 EXCEPTION: ObjectUnsubscribedError.

如果我没有取消订阅,每次进入列表时,都会堆叠一个新订阅,并且当收到next()时会触发所有订阅.

Thi*_*ier 72

我会以这种方式获得订阅并取消订阅,而不是直接在主题上:

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(); // <-------
}
Run Code Online (Sandbox Code Playgroud)

  • 你能提一下为什么直接打电话取消订阅注射的主题参考不起作用? (10认同)
  • “ Subject类中的unsubscribe方法实际上并未取消任何订阅。相反,它将主题标记为已关闭,并将其内部数组订阅的观察者设置为null”。更多详细信息:https://blog.angularindepth.com/rxjs-closed -subjects-1b6f76c1b63c (2认同)

Wor*_*ver 12

.subscribe()返回订阅

  • 您应该使用它来取消订阅


例如,Parent有一个reloadSubject:Subject;

  • child1 - >订阅
  • child2 - >订阅

child1 - "WORKS" - >取消订阅他的订阅

ngOnInit{ 
  sub: Subscription = parent.subscribe();
}
onDestroy{
  this.sub.unsubscribe();
}
Run Code Online (Sandbox Code Playgroud)


child2 - "不工作" - >取消订阅整个父母

ngOnInit{ 
  parent.subscribe();
}

onDestroy{
  parent.unsubscribe();
}
Run Code Online (Sandbox Code Playgroud)

如果你打电话给父母取消订阅,两个孩子都不见了.
如果您取消订阅从.subscribe()获得的订阅,则只有一个孩子取消订阅.

如果我错了请纠正我!