我正在实施angular4客户端应用程序 我添加了一些服务,它们从后端发出一些http请求 然后,它开始抛出 ObjectUnsubscribedError 以下是截图:
经过一些研究后,我发现了来自here
的以下警告"An error thrown when an action is invalid because the object has been unsubscribed."
我猜是ReactJs rxjs/Subject
属性引起的问题。我想,我可能会取消订阅,但我的取消订阅代码是 ngOnDestroy()
方法,这是代码的退出。
所以,我找不到合适的解决方案或问题的确切原因
有任何建议或帮助吗?
感谢
我的代码的一部分:
import {Component, Inject, OnDestroy, OnInit} from '@angular/core';
import {Subject} from "rxjs/Subject";
import {APP_CONFIG} from "../../../config/app.config";
import {IAppConfig} from "../../../config/iapp.config";
import {HomelandsService} from "../../../shared/services/homelands.service";
import {SearchService} from "../../../shared/services/search.service";
import {Kelime} from "../../../shared/models/Kelime";
import {City} from "../../../shared/models/homeland/City";
import {County} from "../../../shared/models/homeland/County";
import {Area} from "../../../shared/models/homeland/Area";
import {Neighborhood} from "../../../shared/models/homeland/Neighborhood";
import {HomelandSearchInfo} from "../../../shared/models/HomelandSearchInfo";
@Component({
selector: 'app-homeland-search-field',
templateUrl: './homeland-search-field.component.html',
styleUrls: ['./homeland-search-field.component.css'],
providers: []
})
export class HomelandSearchFieldComponent implements OnInit, OnDestroy {
//citiesChanges = new Subject<City[]>();
countiesChanges = new Subject<County[]>();
areasChanges = new Subject<Area[]>();
neighborhoodsChanges = new Subject<Neighborhood[]>();
cities: City[] = this.appConfig.cities;
counties: County[];
areas: Area[];
neighborhoods: Neighborhood[];
homelandSearchInfo: HomelandSearchInfo = {
cityId: null,
countyId: null,
areaId: null,
neighborhoodId: null
};
kelimeler: Kelime[];
constructor(private homelandsService: HomelandsService,
private searchService: SearchService,
@Inject(APP_CONFIG) private appConfig: IAppConfig) { }
ngOnInit() {
this.countiesChanges = this.homelandsService.countiesChanges;
this.areasChanges = this.homelandsService.areasChanges;
this.neighborhoodsChanges = this.homelandsService.neighborhoodsChanges;
this.countiesChanges.subscribe(
(counties: County[]) => {
this.counties = counties;
}
);
this.areasChanges.subscribe(
(areas: Area[]) => {
this.areas = areas;
}
);
this.neighborhoodsChanges.subscribe(
(neighborhoods: Neighborhood[]) => {
this.neighborhoods = neighborhoods;
}
);
/*this.citiesChanges = this.homelandsService.citiesChanges;
this.citiesChanges.subscribe(
(cities: City[]) => {
this.cities = cities;
// Loads the cities of Turkey=223
this.cities = this.homelandsService.getCities().filter((item)=> item.countryId == 223);
}
);*/
}
ngOnDestroy(){
this.countiesChanges.unsubscribe();
this.areasChanges.unsubscribe();
this.neighborhoodsChanges.unsubscribe();
}
// ############################## HOMELAND EVENTs & HELPERs ##############################
onSelectCity(cityId: number){
this.homelandSearchInfo.cityId = cityId;
this.homelandSearchInfo.countyId = null;
this.homelandSearchInfo.areaId = null;
this.homelandSearchInfo.neighborhoodId = null;
//this.counties = this.homelandsService.getCounties().filter((item)=> item.cityId == cityId);
//this.homelandsService.httpGetCountiesByCityId(cityId);
this.areas = [];
this.neighborhoods = [];
}
onSelectCounty(countyId: number){
this.homelandSearchInfo.countyId = countyId;
this.homelandSearchInfo.areaId = null;
this.homelandSearchInfo.neighborhoodId = null;
//this.areas = this.homelandsService.getAreas().filter((item)=> item.countyId == countyId );
//this.homelandsService.httpGetAreasByCountyId(countyId);
this.neighborhoods = [];
}
onSelectArea(areaId: number){
this.homelandSearchInfo.areaId = areaId;
this.homelandSearchInfo.neighborhoodId = null;
console.log(areaId);
//this.neighborhoods = this.homelandsService.getNeighborhoods().filter((item)=> item.areaId == areaId );
//this.homelandsService.httpGetNeighborhoodsByAreaId(areaId);
}
onSelectNeighborhood(neighborhoodId: number){
//this.homelandSearchInfo.neighborhoodId = neighborhoodId;
}
onSearch(){
console.log(this.homelandSearchInfo);
//1.search servise ilgili bilgileri gönderip sonuçları kelimelerde listelemek.
this.searchService.searchHomeland(this.homelandSearchInfo);
}}
====================
import {Inject, Injectable} from '@angular/core';
import {Http} from "@angular/http";
import {Subject} from "rxjs/Subject";
import {APP_CONFIG} from "../../config/app.config";
import {IAppConfig} from "../../config/iapp.config";
import {City} from "../models/homeland/City";
import {County} from "../models/homeland/County";
import {Area} from "../models/homeland/Area";
import {Neighborhood} from "../models/homeland/Neighborhood";
import {Observable} from "rxjs/Observable";
import "rxjs/add/operator/catch";
@Injectable()
export class HomelandsService {
citiesChanges = new Subject<City[]>();
countiesChanges = new Subject<County[]>();
areasChanges = new Subject<Area[]>();
neighborhoodsChanges = new Subject<Neighborhood[]>();
cities: City[] = this.appConfig.cities;
counties: County[] = [];
areas: Area[] = [];
neighborhoods: Neighborhood[] = [];
constructor(private http: Http,
@Inject(APP_CONFIG) private appConfig: IAppConfig) {
//this.httpGetCities();
//this.httpGetCounties();
//this.httpGetAreas();
//this.httpGetNeighborhoods();
}
getCities(){
return this.cities.slice();
}
getCounties(){
return this.counties.slice();
}
getAreas(){
return this.areas.slice();
}
getNeighborhoods(){
return this.neighborhoods.slice();
}
httpGetCities(){
let url: string = this.appConfig.backendURL + 'cities/countryId=' + 223;
this.http.get(url)
.map(
(response) => {
const backendResponse = response.json();
if(backendResponse.success){
const cities: City[] = backendResponse.item;
console.log(cities);
return cities;
}else{
console.error(backendResponse.msg);
return Observable.throw(backendResponse.msg)
}
}
)
.catch(
(error: Response) => {
console.error(error);
return Observable.throw(error);
}
)
.subscribe(
(cities: City[]) => {
this.cities = cities;
this.citiesChanges.next(this.cities.slice());
},
(error: Error) => {
console.error(error);
}
)
}
httpGetCounties(){
let url: string = this.appConfig.backendURL + 'counties/';
this.http.get(url)
.map(
(response) => {
const backendResponse = response.json();
if(backendResponse.success){
const counties: County[] = backendResponse.item;
console.log(counties);
return counties;
}else{
console.error(backendResponse.msg);
return Observable.throw(backendResponse.msg)
}
}
)
.catch(
(error: Response) => {
console.error(error);
return Observable.throw(error);
}
)
.subscribe(
(counties: County[]) => {
this.counties = counties;
this.countiesChanges.next(this.counties.slice());
},
(error: Error) => {
console.error(error);
}
)
}
httpGetCountiesByCityId(cityId: number){
let url: string = this.appConfig.backendURL + 'counties/cityId=' + cityId;
this.http.get(url)
.map(
(response) => {
const backendResponse = response.json();
if(backendResponse.success){
const counties: County[] = backendResponse.item;
console.log(counties);
return counties;
}else{
console.error(backendResponse.msg);
return Observable.throw(backendResponse.msg)
}
}
)
.catch(
(error: Response) => {
console.error(error);
return Observable.throw(error);
}
)
.subscribe(
(counties: County[]) => {
this.counties = counties;
this.countiesChanges.next(this.counties.slice());
},
(error: Error) => {
console.error(error);
}
)
}
httpGetAreas(){
let url: string = this.appConfig.backendURL + 'areas/';
this.http.get(url)
.map(
(response) => {
const backendResponse = response.json();
if(backendResponse.success){
const areas: Area[] = backendResponse.item;
console.log(areas);
return areas;
}else{
console.error(backendResponse.msg);
return Observable.throw(backendResponse.msg)
}
}
)
.catch(
(error: Response) => {
console.error(error);
return Observable.throw(error);
}
)
.subscribe(
(areas: Area[]) => {
this.areas = areas;
this.areasChanges.next(this.areas.slice());
},
(error: Error) => {
console.error(error);
}
)
}
httpGetAreasByCountyId(countyId: number){
let url: string = this.appConfig.backendURL + 'areas/countyId=' + countyId;
this.http.get(url)
.map(
(response) => {
const backendResponse = response.json();
if(backendResponse.success){
const areas: Area[] = backendResponse.item;
console.log(areas);
return areas;
}else{
console.error(backendResponse.msg);
return Observable.throw(backendResponse.msg)
}
}
)
.catch(
(error: Response) => {
console.error(error);
return Observable.throw(error);
}
)
.subscribe(
(areas: Area[]) => {
this.areas = areas;
this.areasChanges.next(this.areas.slice());
},
(error: Error) => {
console.error(error);
}
)
}
httpGetNeighborhoods(){
let url: string = this.appConfig.backendURL + 'neighborhoods/';
this.http.get(url)
.map(
(response) => {
const backendResponse = response.json();
if(backendResponse.success){
const neighborhoods: Neighborhood[] = backendResponse.item;
console.log(neighborhoods);
return neighborhoods;
}else{
console.error(backendResponse.msg);
return Observable.throw(backendResponse.msg)
}
}
)
.catch(
(error: Response) => {
console.error(error);
return Observable.throw(error);
}
)
.subscribe(
(neighborhoods: Neighborhood[]) => {
this.neighborhoods = neighborhoods;
this.neighborhoodsChanges.next(this.neighborhoods.slice());
},
(error: Error) => {
console.error(error);
}
)
}
httpGetNeighborhoodsByAreaId(areaId: number){
let url: string = this.appConfig.backendURL + 'neighborhoods/areaId=' + areaId;
this.http.get(url)
.map(
(response) => {
const backendResponse = response.json();
if(backendResponse.success){
const neighborhoods: Neighborhood[] = backendResponse.item;
console.log(neighborhoods);
return neighborhoods;
}else{
console.error(backendResponse.msg);
return Observable.throw(backendResponse.msg)
}
}
)
.catch(
(error: Response) => {
console.error(error);
return Observable.throw(error);
}
)
.subscribe(
(neighborhoods: Neighborhood[]) => {
this.neighborhoods = neighborhoods;
this.neighborhoodsChanges.next(this.neighborhoods.slice());
},
(error: Error) => {
console.error(error);
}
)
}
}
更新
我已经删除了ngOnDestroy(
)方法中的取消订阅代码,错误消失了。但是,必须在代码中的某处取消订阅主题。所以,问题实际上并未解决。有什么建议???
答案 0 :(得分:0)
创建Subscription
并取消订阅,而不是退出主题本身。取消订阅主题或行为主题将关闭可观察对象。试试这个:
import { Subject, Subscription } from 'rxjs';
为订阅创建属性并将其分配给订阅。
countiesChangesSubscription: Subscription;
this.countiesChangesSubscription = this.countiesChanges.subscribe(...)
然后仅取消订阅订阅,而不是观察到的订阅。
ngOnDestroy() {
this.countiesChangesSubscription.unsubscribe();
}
对您不想在销毁时关闭的所有订阅执行此操作。