I'm developing a service that processes an xml file and returns a data structure of interfaces.
At first I thought that the service had correctly returned all the data, but then I realized some unclear things, in particular when I was going to read the data structure in a component.
This is my service:
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;
}
And this is my component:
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';
};
}
}
The very strange thing is with those three logs. We can see different things between them.
With the first log I can see the whole data structure in console.
With the second, nothing happens.
With the third, the length is equal to 0, which is not true because as shown in the first log, the data structure is full...!
I don't understand why these oddities. Is there anything I missed from the angular documentation?
PS: I don't want to make the subscription in the component, otherwise I would have already solved... I want to separate logic from visualization and create the data structure in the service, as I did.