作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Angular 11,并且我正在使用 访问我的组件模板中的 observable异步 管道。
路线的第一次加载,一切正常。没有错误。当我离开页面并返回时,出现以下错误:
组件模板:
[层]="layers.layerConfig"
showLayersPanel="true"id="RIS-map">
组件
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { FullMapViewService } from '../services/full-map-view.service';
import { RISLayerConfigResponse } from '@RM/interfaces';
import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'RM-full-map-view',
templateUrl: './full-map-view.component.html',
styleUrls: ['./full-map-view.component.scss']
})
export class FullMapViewComponent implements OnInit, OnDestroy {
layers$: Observable<RISLayerConfigResponse>;
destroyed$: Subject<boolean> = new Subject();
constructor(private fullMapViewService: FullMapViewService) {}
ngOnInit(): void {
this.fullMapViewService.setParamsRequiredForRIS();
this.fullMapViewService.initializeRISLayerCreationService();
this.layers$ = this.fullMapViewService
.getLayersForAllProjects()
.pipe(takeUntil(this.destroyed$));
}
ngOnDestroy() {
this.destroyed$.next(true);
}
}
全 map -view.service.ts
import { DEPLOYMENT_PATH, SET_FROM_SERVER } from '@XYZ/RIS';
import {
DataSet,
DatasetsAndLayerConfig,
RISLayerConfigResponse,
RISLayerSettingsWithKind,
Layer,
LayerConfig,
UpdateViewVCS
} from '@XYZ/interfaces';
import { Injectable, OnDestroy } from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import { API_PATHS } from '../../api-paths';
import { BaseAPIService } from '@XYZ/core';
import { ClauseGenerationUtility } from '../../utils/clause-generation/clause-generation.util';
import { RISLayerCreationService } from '@ABC-innersource/RIS-canvas';
import { LAYER_COLOR_PALLET } from '../../services/services.constant';
import { map } from 'rxjs/operators';
@Injectable()
export class FullMapViewService implements OnDestroy {
layersMappingConfiguration: {};
layers: LayerConfig;
private clauseGenerator = new ClauseGenerationUtility();
private addUpdateVCSForKindSubscriptions: Subscription[];
private initializeRISLayerCreationServiceSubscription: Subscription;
private deploymentUrl: string;
private appKey: string;
private ABCDataPartitionId: string;
private sToken: string;
constructor(
private baseAPIService: BaseAPIService,
private layerCreationService: RISLayerCreationService
) {}
// eslint-disable-next-line max-lines-per-function
getLayersForAllProjects(): Observable<RISLayerConfigResponse> {
return this.baseAPIService
.get(API_PATHS.LAYERS.GET_LAYERS + '/projects/all')
.pipe(
map((res: DatasetsAndLayerConfig) => {
return res;
}),
// eslint-disable-next-line max-lines-per-function
map((datasetsAndLayerConfig: DatasetsAndLayerConfig) => {
const datasets = [...datasetsAndLayerConfig.datasets];
const notConfiguredKinds = [
...datasetsAndLayerConfig.layerConfig.notConfiguredKinds
];
const notConfiguredKindsLayers = this.getNonConfiguredKindsLayers(
notConfiguredKinds
);
const layers = this.combineLayersAndNotConfiguredKindsLayers(
datasetsAndLayerConfig.layerConfig.layerConfig,
notConfiguredKindsLayers
);
const kindsLayersHashmap = this.getKindsLayersHashmap(layers);
const layersByDatasets = datasets
.map((dataset: DataSet) => {
return {
...this.updateLayersWithDatasetNameAndClauses(
kindsLayersHashmap,
dataset
)
};
})
.filter((layer) => {
return Object.keys(layer).length !== 0;
})
.map((layer, index) => {
return {
...this.assignColourToLayer(layer, index)
};
});
return {
layerConfig: layersByDatasets,
notConfiguredKinds: []
};
})
);
}
setParamsRequiredForRIS(): void {
this.sToken = SET_FROM_SERVER;
this.deploymentUrl = DEPLOYMENT_PATH;
this.appKey = SET_FROM_SERVER;
this.ABCDataPartitionId = SET_FROM_SERVER;
}
initializeRISLayerCreationService(): void {
this.initializeRISLayerCreationServiceSubscription = this.layerCreationService
.initialize(
this.sToken,
this.deploymentUrl,
this.appKey,
this.ABCDataPartitionId
)
.subscribe();
}
ngOnDestroy(): void {
this.initializeRISLayerCreationServiceSubscription.unsubscribe();
this.addUpdateVCSForKindSubscriptions.forEach(
(subscription: Subscription) => {
subscription.unsubscribe();
}
);
}
private updateLayersWithDatasetNameAndClauses(
kindsLayersHashmap: Map<string, RISLayerSettingsWithKind>,
dataset: DataSet
): RISLayerSettingsWithKind {
const currentDataset = { ...dataset };
const datasetKind = this.generateKindFromDataset(currentDataset);
const layer = kindsLayersHashmap.get(datasetKind);
const queryRef = this.getFormattedQuery(
currentDataset.dataSetDefinition.queryDefinition.queryRef
);
const clause = this.clauseGenerator.generateClause(queryRef);
if (!layer) {
return undefined;
}
layer.name = currentDataset.name;
layer.tableInfo.where = clause;
return JSON.parse(JSON.stringify(layer));
}
private generateKindFromDataset(dataset: DataSet): string {
const currentDataset = { ...dataset };
const datasetQueryDefinition =
currentDataset.dataSetDefinition.queryDefinition;
return `${datasetQueryDefinition.authority}:${datasetQueryDefinition.source}:${datasetQueryDefinition.entity}:${datasetQueryDefinition.version}`;
}
private getKindsLayersHashmap(
layers: RISLayerSettingsWithKind[]
): Map<string, RISLayerSettingsWithKind> {
const kindsLayersHashmap = new Map();
const allLayers = [...layers];
allLayers.forEach((layer: RISLayerSettingsWithKind) => {
kindsLayersHashmap.set(layer.kind, layer);
});
return kindsLayersHashmap;
}
private getNonConfiguredKindsLayers(
kinds: string[]
): RISLayerSettingsWithKind[] {
const notConfiguredKindsLayers: RISLayerSettingsWithKind[] = [];
kinds.forEach((kind) => {
const layer: RISLayerSettingsWithKind[] = this.layerCreationService.getLayerInfoByKindName(
kind
) as RISLayerSettingsWithKind[];
if (layer.length > 0) {
layer[0].kind = kind;
notConfiguredKindsLayers.push(layer[0]);
this.addUpdateRISLayerInVCS({ kind: kind, configuration: layer[0] });
}
});
return notConfiguredKindsLayers;
}
private addUpdateRISLayerInVCS(layer: Layer): void {
const currentLayer = { ...layer };
const updateViewPayload: UpdateViewVCS = {
control: 'RIS',
definition: [{ ...currentLayer.configuration }]
};
this.addUpdateVCSForKind(currentLayer.kind, updateViewPayload);
}
private addUpdateVCSForKind(kind: string, payload: UpdateViewVCS): void {
const subscription = this.baseAPIService
.post(
`${API_PATHS.CONFIG.VIEW.UPDATE_RIS_VIEW_CONFIG}`.replace(
'${kind}',
kind
),
payload
)
.subscribe();
this.addUpdateVCSForKindSubscriptions.push(subscription);
}
private combineLayersAndNotConfiguredKindsLayers(
layers: RISLayerSettingsWithKind[],
notConfiguredKindsLayers: RISLayerSettingsWithKind[]
): RISLayerSettingsWithKind[] {
const allLayers = [...layers];
const allNotConfiguredKindsLayers = [...notConfiguredKindsLayers];
return [...allLayers, ...allNotConfiguredKindsLayers];
}
private getFormattedQuery(query: string): string {
let formattedQuery = '';
if (
this.clauseGenerator.hasAndOperator(query) ||
this.clauseGenerator.hasOrOperator(query)
) {
formattedQuery = this.clauseGenerator.isWrappedWithRoundBrackets(query)
? query
: `(${query})`;
return formattedQuery;
}
return formattedQuery;
}
private assignColourToLayer(
layer: RISLayerSettingsWithKind,
index: number
): RISLayerSettingsWithKind {
const colors = LAYER_COLOR_PALLET;
const currentLayer = JSON.parse(JSON.stringify(layer));
currentLayer.style.rules[0].style.fillColor = colors[index];
currentLayer.style.rules[0].style.borderColor = '#000';
return currentLayer;
}
}
例如路线 B 是我的包含可观察的组件
ObjectUnsubscribedErrorImpl {message: "object unsubscribed", name: "ObjectUnsubscribedError"}
message: "object unsubscribed"
name: "ObjectUnsubscribedError"
完整堆栈跟踪快照如下所示:
core.js:6162 ERROR ObjectUnsubscribedErrorImpl {message: "object unsubscribed", name: "ObjectUnsubscribedError"}message: "object unsubscribed"name: "ObjectUnsubscribedError"__proto__: Error
defaultErrorLogger @ core.js:6162
handleError @ core.js:6210
(anonymous) @ core.js:29503
invoke @ zone-evergreen.js:364
run @ zone-evergreen.js:123
runOutsideAngular @ core.js:28439
tick @ core.js:29503
(anonymous) @ core.js:29372
invoke @ zone-evergreen.js:364
onInvoke @ core.js:28510
invoke @ zone-evergreen.js:363
run @ zone-evergreen.js:123
run @ core.js:28394
next @ core.js:29371
schedulerFn @ core.js:25848
__tryOrUnsub @ Subscriber.js:183
next @ Subscriber.js:122
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
emit @ core.js:25838
checkStable @ core.js:28447
onLeave @ core.js:28560
onInvokeTask @ core.js:28504
invokeTask @ zone-evergreen.js:398
runTask @ zone-evergreen.js:167
invokeTask @ zone-evergreen.js:480
invokeTask @ zone-evergreen.js:1621
globalZoneAwareCallback @ zone-evergreen.js:1658
load (async)
customScheduleGlobal @ zone-evergreen.js:1773
scheduleTask @ zone-evergreen.js:385
onScheduleTask @ zone-evergreen.js:272
scheduleTask @ zone-evergreen.js:378
scheduleTask @ zone-evergreen.js:210
scheduleEventTask @ zone-evergreen.js:236
(anonymous) @ zone-evergreen.js:1928
(anonymous) @ http.js:1805
_trySubscribe @ Observable.js:42
subscribe @ Observable.js:28
call @ catchError.js:14
subscribe @ Observable.js:23
call @ catchError.js:14
subscribe @ Observable.js:23
innerSubscribe @ innerSubscribe.js:67
_innerSub @ mergeMap.js:57
_tryNext @ mergeMap.js:51
_next @ mergeMap.js:34
next @ Subscriber.js:49
(anonymous) @ subscribeToArray.js:3
_trySubscribe @ Observable.js:42
subscribe @ Observable.js:28
call @ mergeMap.js:19
subscribe @ Observable.js:23
call @ filter.js:13
subscribe @ Observable.js:23
call @ map.js:16
subscribe @ Observable.js:23
call @ map.js:16
subscribe @ Observable.js:23
call @ map.js:16
subscribe @ Observable.js:23
createSubscription @ common.js:4224
_subscribe @ common.js:4305
transform @ common.js:4292
ɵɵpipeBind1 @ core.js:25718
FullMapViewComponent_Template @ full-map-view.component.html:2
executeTemplate @ core.js:9549
refreshView @ core.js:9418
refreshComponent @ core.js:10584
refreshChildComponents @ core.js:9215
refreshView @ core.js:9468
refreshEmbeddedViews @ core.js:10538
refreshView @ core.js:9442
refreshEmbeddedViews @ core.js:10538
refreshView @ core.js:9442
refreshComponent @ core.js:10584
refreshChildComponents @ core.js:9215
refreshView @ core.js:9468
renderComponentOrTemplate @ core.js:9532
tickRootContext @ core.js:10758
detectChangesInRootView @ core.js:10783
detectChanges @ core.js:22751
tick @ core.js:29491
(anonymous) @ core.js:29372
invoke @ zone-evergreen.js:364
onInvoke @ core.js:28510
invoke @ zone-evergreen.js:363
run @ zone-evergreen.js:123
run @ core.js:28394
next @ core.js:29371
schedulerFn @ core.js:25848
__tryOrUnsub @ Subscriber.js:183
next @ Subscriber.js:122
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
emit @ core.js:25838
checkStable @ core.js:28447
onHasTask @ core.js:28527
hasTask @ zone-evergreen.js:419
_updateTaskCount @ zone-evergreen.js:440
_updateTaskCount @ zone-evergreen.js:263
runTask @ zone-evergreen.js:184
drainMicroTaskQueue @ zone-evergreen.js:569
invokeTask @ zone-evergreen.js:484
invokeTask @ zone-evergreen.js:1621
globalZoneAwareCallback @ zone-evergreen.js:1647
如果你看到,
FullMapViewComponent_Template @ full-map-view.component.html:2
提到模板上的 observable 存在问题。
最佳答案
我搜索了 ObjectUnsubscribedError 的地方被抛出 rxjs github 项目并试图在实际抛出此错误时获得洞察力。我可以在 this 上找到最好的见解测试。我试着总结一下我是如何理解这种行为的:
当您直接取消订阅某个主题时,它将被关闭。每当您尝试重新订阅它时,它都会抛出 ObjectUnsubscribedError。
这意味着您很可能持有您的主题(在您的服务中),尽管您的组件被丢弃并取消订阅。当您重新路由到组件时,它会尝试再次订阅,然后抛出错误。我从上面的链接测试中获取了一个最小的可重现示例:
const { Subject } = rxjs;
const subject = new Subject();
subject.subscribe()
subject.next("foo")
subject.unsubscribe()
try {
subject.subscribe()
} catch (e) {
console.error("the error: ", e)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.min.js"></script>
unsubscribe
。在
subscription
在您的组件中,然后是新组件特定主题中的值。
// Your subscription on wich you can unsubscribe
private copySubjectSubscription;
// This subject is used in your component with the async pipe
public readonly copySubject = new Subject();
constructor(serviceWithSubject) {
this.copySubjectSubscription =
serviceWithSubject.subject.subscribe(e => copySubject.next())
}
ngOnDestroy() {
this.copySubjectSubscription.unsubscribe();
}
由于我不了解您的代码并且时间有限,您可能会找到一个更优雅的解决方案来复制主题及其值而无需直接取消订阅。
Observables
在组件中。
关于javascript - Angular 模板中可观察对象上的 ObjectUnsubscribedErrorImpl,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67235013/
我正在使用 Angular 11,并且我正在使用 访问我的组件模板中的 observable异步 管道。 路线的第一次加载,一切正常。没有错误。当我离开页面并返回时,出现以下错误: 组件模板: *ng
我是一名优秀的程序员,十分优秀!