我有一个丑陋的嵌套对象,其中有一个需要http发布订阅的子对象,此方法有效。嵌套对象和父对象的上游都是列表对象本身。我需要做的是这个孩子的父母需要进行汇总计算。
我的问题:您可以/如何在同一对象中订阅嵌套订阅?
这是我原来的http型号:
export interface GatewayExtractRun {
clientName?: string;
extractruns?: Array<GatewayExtractExtractRuns>;
}
export interface GatewayExtractExtractRuns {
extractName?: string;
runs?: Array<GatewayExtractRuns>;
}
export interface GatewayExtractRuns {
queryExecutionId?: string;
runTime?: string;
extractSqlDefinition?: string;
isIncremental?: string;
}
这是我(想我)需要的:
export class ExtractsViewModel {
clientName: string;
extractRuns?: ExtractRunsViewModel[];
}
export class ExtractRunsViewModel implements GatewayExtractExtractRuns {
public extractName?: string;
public runs?: ExtractRunViewModel[];
public statusGreenCount = 0; <-- sum/calculation
public statusRedCount = 0; <-- sum/calculation
public statusUnknownCount = 0; <-- sum/calculation
public statusInProcessCount = 0; <--sum/calculation
}
export class ExtractRunViewModel implements GatewayExtractRuns {
queryExecutionId?: string;
runTime?: string;
extractSqlDefinition?: string;
isIncremental?: string;
endstatus: string; <-- NEW: returns from a subscription
}
这是我当前的代码,它的编写更像是csharp而不是打字稿,但这是我所能做的最好的事情。它读下来,只是将一个模型转换为具有更多字段的视图模型,因为该模型是从http客户端返回的接口类型:
public clientConfigurationObs: Observable<GatewayExtractRun>;
public clientConfiguration: GatewayExtractRun;
public extractRunsViewModel: ExtractsViewModel;
constructor(
private readonly service1: ConfigurationService,
private readonly trackerService: TrackerService,
) { }
private setupClientConfiguration(): void {
this.clientConfigurationObs = this.service1.getClientExtractsRunStats(
this.clientName,
);
this.handleClientConfiguration();
}
private handleClientConfiguration(): void {
this.clientConfigurationObs.subscribe(
(gatewayextractrun) => {
this.clientConfiguration = gatewayextractrun;
if (gatewayextractrun.clientName != null) {
this.extractRunsViewModel = this.convertGatewayExtractRunToViewModel(
gatewayextractrun
);
}
},
(err) => {
console.error(err);
this.clientConfiguration = undefined;
},
);
console.log('extractsRunsViewModel complete');
console.log(this.extractRunsViewModel);
}
private convertGatewayExtractRunToViewModel(
rootExtract: GatewayExtractRun,
): ExtractsViewModel {
const returnModel: ExtractsViewModel = {
clientName: rootExtract.clientName,
extractRuns: this.convertGatewayExtractExtractRunsViewModel(
rootExtract.extractruns,
),
};
return returnModel;
}
private convertGatewayExtractExtractRunsViewModel(
parentExtract: GatewayExtractExtractRuns[],
): ExtractRunsViewModel[] {
// tslint:disable-next-line:prefer-const
let returnModel: ExtractRunsViewModel[] = [];
parentExtract.forEach((element) => {
const singleItemReturnModel: ExtractRunsViewModel = this.transformGatewayExtractExtractRunsToViewModel(
element,
);
returnModel.push(singleItemReturnModel);
});
return returnModel;
}
/**
* Maps a Gateway extract run from a GatewayExtractRuns to a ExtractViewModel by adding a end extract status.
* @param parentExtract a single extract's run to be transformed into a temp view model with an 'UNKNOWN' end status.
*/
private transformGatewayExtractExtractRunsToViewModel(
parentExtract: GatewayExtractExtractRuns,
): ExtractRunsViewModel {
let returnModel: ExtractRunsViewModel = {
extractName: parentExtract.extractName,
runs: this.convertGatewayExtractRunsToViewModel(parentExtract.runs),
statusGreenCount: 0,
statusInProcessCount: 0,
statusRedCount: 0,
statusUnknownCount: 0,
};
return returnModel;
}
/**
* Converts a list of GatewayExtractRuns, tied to parent extract name, into a list of ExtractRunViewModels
* which have a extract end extract status column. Also at this time the parent extract will recieve
* updated summary status data for the sucessful/failed/unknown/in process extracts.
* @param childExtract a single extract's run to be transformed into a temp view model with an 'UNKNOWN' end status.
*/
private convertGatewayExtractRunsToViewModel(
childExtract: GatewayExtractRuns[],
): ExtractRunViewModel[] {
let returnModel: ExtractRunViewModel[] = [];
childExtract.forEach((element) => {
const singleItemReturnModel: ExtractRunViewModel = this.transformGatewayExtractRunsToViewModel(
element,
);
// true starting point of conversion, retrieve the batch status
this.trackerService
.putBatchStatusByFile(element.queryExecutionId)
.subscribe((response) => {
// 2 part, we need to update the child and the parent summary data for job status's
singleItemReturnModel.endstatus = response.jobStatus;
returnModel.push(singleItemReturnModel);
// ***************************************
// ALSO UPDATE PARENT HERE IF POSSIBLE
// parentExtract = this.updateQueryStatusCounts(parentExtract, singleItemReturnModel.endstatus);
// ***************************************
},
(err) => {
console.error(err);
this.clientConfiguration = undefined;
});
});
return returnModel;
}
/**
* Maps a Gateway extract run from a GatewayExtractRuns to a ExtractViewModel by adding a end extract status.
* @param childExtract a single extract's run to be transformed into a temp view model with an 'UNKNOWN' end status.
*/
private transformGatewayExtractRunsToViewModel(
childExtract: GatewayExtractRuns,
): ExtractRunViewModel {
const returnModel: ExtractRunViewModel = {
queryExecutionId: childExtract.queryExecutionId,
runTime: childExtract.runTime,
extractSqlDefinition: childExtract.extractSqlDefinition,
isIncremental: childExtract.isIncremental,
endstatus: 'UNKNOWN',
};
return returnModel;
}
private updateQueryStatusCounts(
jobstatus: string,
modelToUpdate: ExtractRunsViewModel,
): ExtractRunsViewModel {
switch (this.determineJobStatus(jobstatus)) {
case 2: {
modelToUpdate.statusGreenCount =
modelToUpdate.statusGreenCount + 1;
break;
}
case 1: {
modelToUpdate.statusInProcessCount =
modelToUpdate.statusInProcessCount + 1;
break;
}
case 0: {
modelToUpdate.statusUnknownCount =
modelToUpdate.statusUnknownCount + 1;
break;
}
case -1: {
modelToUpdate.statusRedCount = modelToUpdate.statusRedCount + 1;
break;
}
default: {
break;
}
}
return modelToUpdate;
}
private determineJobStatus(jobstatus: string) {
if (jobstatus === 'SUCCEEDED') {
return 2;
} else if (jobstatus === 'FAILED') {
return -1;
} else if (
jobstatus === 'PENDING' ||
jobstatus === 'RUNNABLE' ||
jobstatus === 'RUNNING' ||
jobstatus === 'STARTING' ||
jobstatus === 'SUBMITTED'
) {
return 1;
} else {
return 0;
}
}
因此,我们从页面加载开始并检索这些客户端:
private setupClientConfiguration(): void {
this.clientConfigurationObs = this.service1.getClientExtractsRunStats(
this.clientName,
);
this.handleClientConfiguration();
}
然后,该过程从树开始(按照树的列出顺序)。我感到困惑的是,我需要的数据在订阅中:
private convertGatewayExtractRunsToViewModel(
childExtract: GatewayExtractRuns[],
): ExtractRunViewModel[] {
let returnModel: ExtractRunViewModel[] = [];
childExtract.forEach((element) => {
const singleItemReturnModel: ExtractRunViewModel = this.transformGatewayExtractRunsToViewModel(
element,
);
// true starting point of conversion, retrieve the batch status
this.trackerService
.putBatchStatusByFile(element.queryExecutionId)
.subscribe((response) => {
// 2 part, we need to update the child and the parent summary data for job status's
singleItemReturnModel.endstatus = response.jobStatus;
returnModel.push(singleItemReturnModel);
},
(err) => {
console.error(err);
this.clientConfiguration = undefined;
});
});
return returnModel;
}
需要其父级来计算ExtractRunsViewModel的总和。
我试图传递客户端,并提取名称传递给订阅,然后循环订阅以更新其父母。但这导致结果不一致。