Mem*_*mmo 6 typescript angular angular8
我正在开发一个处理 xml 文件并返回接口数据结构的服务。
起初我以为服务已经正确返回了所有数据,但后来我意识到一些不清楚的事情,特别是当我要读取组件中的数据结构时。
这是我的服务:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { AppConfig } from 'src/app/app.config';
import { forkJoin, Subscription } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class BibliographyParserService {
private editionUrls = AppConfig.evtSettings.files.editionUrls || [];
private bibliographicCitations: Array<BibliographicCitation> = [];
private subscriptions: Array<Subscription> = [];
constructor(
private http: HttpClient,
) {
}
private getHttpCallsOBSStream() {
return this.editionUrls.map((path) => this.http.get(path, { responseType: 'text'}));
}
public getBibliographicCitations(): Array<BibliographicCitation> {
const parser = new DOMParser();
this.subscriptions.push(forkJoin(this.getHttpCallsOBSStream()).subscribe((responses) => {
responses.forEach(response => {
Array.from(parser.parseFromString(response, 'text/xml').getElementsByTagName('bibl')).forEach(citation => {
if (citation.getElementsByTagName('author').length === 0 &&
citation.getElementsByTagName('title').length === 0 &&
citation.getElementsByTagName('date').length === 0) {
const interfacedCitation: BibliographicCitation = {
title: citation.textContent.replace(/\s+/g, ' '),
};
if (!this.bibliographicCitations.includes(interfacedCitation)) { this.bibliographicCitations.push(interfacedCitation); }
} else {
const interfacedCitation: BibliographicCitation = {
authors: citation.getElementsByTagName('author'),
title: String(citation.getElementsByTagName('title')[0]).replace(/\s+/g, ' '),
date: citation.getElementsByTagName('date')[0],
};
if (!this.bibliographicCitations.includes(interfacedCitation)) { this.bibliographicCitations.push(interfacedCitation); }
}
});
});
}));
return this.bibliographicCitations;
}
}
export interface BibliographicCitation {
authors?: HTMLCollectionOf<Element>;
title: string;
date?: Element;
}
Run Code Online (Sandbox Code Playgroud)
这是我的组件:
import { Component, AfterViewInit } from '@angular/core';
import { BibliographyParserService } from 'src/app/services/xml-parsers/bibliography-parser.service';
@Component({
selector: 'evt-bibliography',
templateUrl: './bibliography.component.html',
styleUrls: ['./bibliography.component.scss']
})
export class BibliographyComponent implements AfterViewInit{
constructor(
public bps: BibliographyParserService,
) {
console.log(this.bps.getBibliographicCitations()); // WORKS, return the correct data structure
this.bps.getBibliographicCitations().forEach(console.log); // DOESN'T RETURN ANYTHING!
console.log(this.bps.getBibliographicCitations().length); // RETURN 0
}
ngAfterViewInit() {
(document.querySelectorAll('.cloosingRood')[0] as HTMLElement).onclick = () => {
(document.querySelectorAll('.biblSpace')[0] as HTMLElement).style.display = 'none';
};
}
}
Run Code Online (Sandbox Code Playgroud)
非常奇怪的是这三个日志。我们可以看到他们之间的不同。
通过第一个日志,我可以在控制台中看到整个数据结构。
对于第二个,什么也没有发生。
对于第三个,长度等于0,这是不正确的,因为如第一个日志所示,数据结构已满......!
我不明白为什么会有这些奇怪的事情。我从 angular 文档中遗漏了什么吗?
PS:我不想在组件中进行订阅,否则我早就解决了......我想将逻辑与可视化分开并在服务中创建数据结构,就像我所做的那样。
您不必订阅该服务,但返回一个可观察的。
创建它的方式并不重要,重要的是尊重语法,这对于一个有角度的新手来说并不容易,可以理解!
根据blid给出的答案,我提出了这个解决方案,它可以调解反应式编程和命令式编程,而不会破坏您迄今为止所做的事情。显然,如果某人熟悉命令式编程来创建某些数据结构,他可以自由地做他喜欢做的事情,但如果您决定使用角度环境,您需要了解它提供的所有机会!
无论如何...这就是服务:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { AppConfig } from 'src/app/app.config';
import { forkJoin, Observable } from 'rxjs';
import { shareReplay, map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class BibliographyParserService {
private editionUrls = AppConfig.evtSettings.files.editionUrls || [];
private bibliographicCitations$: Observable<BibliographicCitation[]>;
constructor(
private http: HttpClient,
) {
const parser = new DOMParser();
const bibliographicCitations: Array<BibliographicCitation> = [];
this.bibliographicCitations$ = forkJoin(this.getHttpCallsOBSStream()).pipe( //use pipe...
map(responses => { //...and map
responses.forEach(response => {
Array.from(parser.parseFromString(response, 'text/xml').getElementsByTagName('bibl')).forEach(citation => {
if (citation.getElementsByTagName('author').length === 0 &&
citation.getElementsByTagName('title').length === 0 &&
citation.getElementsByTagName('date').length === 0) {
const interfacedCitation: BibliographicCitation = {
title: citation.textContent.replace(/\s+/g, ' '),
};
if (!bibliographicCitations.includes(interfacedCitation)) { bibliographicCitations.push(interfacedCitation); }
} else {
const interfacedCitation: BibliographicCitation = {
authors: citation.getElementsByTagName('author'),
title: String(citation.getElementsByTagName('title')[0]).replace(/\s+/g, ' '),
date: citation.getElementsByTagName('date')[0],
};
if (!bibliographicCitations.includes(interfacedCitation)) { bibliographicCitations.push(interfacedCitation); }
}
});
});
return bibliographicCitations; //This is the core!!!
}),
shareReplay(1)
);
}
private getHttpCallsOBSStream() {
return this.editionUrls.map((path) => this.http.get(path, { responseType: 'text'}));
}
public getBibliographicCitations(): Observable<Array<BibliographicCitation>> {
return this.bibliographicCitations$;
}
}
export interface BibliographicCitation {
authors?: HTMLCollectionOf<Element>;
title: string;
date?: Element;
}
Run Code Online (Sandbox Code Playgroud)
这是您将在组件中执行的操作的示例:
constructor(
public bps: BibliographyParserService,
) {
this.bps.getBibliographicCitations().subscribe(response => {
response.forEach(cit => {
console.log(cit);
});
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
208 次 |
| 最近记录: |