我正在使用 Angular 16 进行一个涉及使用巴尔干族谱的项目,但我在服务中遇到了问题
这是发出值的函数,正在使用 Angular Core 中的 HttpClient:
this.httpClient.get(url, { headers }).subscribe(
{
next: res => {
console.log(res);
this.apiResponse = res;
this.cdr.detectChanges();
this.zone.run(()=>{
this.specimenData.$specimens.emit(res);
});
this.specimens = this.apiResponse;
},
error: err => {
console.log(err);
}
}
);
如您所见,我尝试查看响应的内容及其用我需要发出的数据定义的内容。 我还尝试让 Angular 检测变化并向该区域执行发射操作,但没有任何效果!当我订阅这个函数中的服务时,我刚刚得到了未定义的信息(这个函数在另一个组件上):
this.specimenData.$specimens.subscribe(value => { this.data = value });
if (this.data != undefined) {
var specimens = [];
const tree = document.getElementById('tree');
if (tree) {
var family = new FamilyTree(tree, {
nodeBinding: {
field_0: "name",
img_0: "img"
},
});
family.load([
{ id: 1, pids: [2], name: "Amber McKenzie", gender: "female", img: "https://cdn.balkan.app/shared/2.jpg" },
{ id: 2, pids: [1], name: "Ava Field", gender: "male", img: "https://cdn.balkan.app/shared/m30/5.jpg" },
{ id: 3, mid: 1, fid: 2, name: "Peter Stevens", gender: "male", img: "https://cdn.balkan.app/shared/m10/2.jpg" },
{ id: 4, mid: 1, fid: 2, name: "Savin Stevens", gender: "male", img: "https://cdn.balkan.app/shared/m10/1.jpg" },
{ id: 5, mid: 1, fid: 2, name: "Emma Stevens", gender: "female", img: "https://cdn.balkan.app/shared/w10/3.jpg" }
]);
}
} else {
console.log("im showing from tree component"+this.data);
}
正如您所看到的,当我从服务的订阅方法传递值时,它传递了一个未定义的值,并且控制台以其他方式显示消息。 很奇怪,因为我在我的应用程序中使用其他服务,它们工作正常,甚至其中一些服务发出像这样的 api 响应,这是他的文件中该服务的代码:
import { EventEmitter, Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class SpecimensService {
constructor() { }
$specimens = new EventEmitter<any>();
}
我尝试将“可注入”更改为“注入”,但没有成功,我还尝试将服务添加到 NgModule 中的提供者,但什么也没有,如果有人对发生的事情有想法或线索,请告诉我,如果您需要更多信息请随时向我索取。
一些可以解决您的问题的观察结果。
EventEmitter
用于父/子组件之间的通信,而不是服务上的通信。
如果您在服务中处理应用程序状态,请使用主题 (
Subject
、BehaviorSubject
、AsyncSubject
、ReplaySubject
),具体取决于
情况。
您不应该在服务中
subscribe
到observables
,有一些例外,但尽量不要这样做,相反,您的服务功能应该返回一个observable
,以便任何组件都可以对可能发生的任何更改做出反应服务(通过使用 next()
)。
避免使用
var
,坚持使用 let
或 const
,具体取决于变量稍后是否会更改。
使用
Angular
与 DOM
进行交互,不要使用原生 javascript
,您可以使用 ViewChild
鉴于这些建议,您可以将当前代码重构如下:
服务
@Injectable({...})
export class SpecimensService {
//Just for demo purposes, I am assuming the data is an array of type yourTypeGoesHere
private _specimen$ = new BehaviorSubject<yourTypeGoesHere[]>([]);
fetchSpecimens(): void {
this._specimen$ = this.get(...);
}
getSpecimens(): Observable<yourTypeGoesHere[]> {
return this._specimen$.asObservable();
}
}
组件 HTML
<div #tree id="tree" class="...">
...
...
</div>
组件
@Component({...})
export class MyComponent implements OnInit {
// this is one way of taking reference from an HTML element
// again, for demo purposes, I am using a div here
@ViewChild('tree') tree!: ElementRef<HTMLDivElement>;
private _specimenService = inject(SpecimenService);
ngOnInit(): void {
// set the data to the service's subject
this._specimenService.fetchSpecimen();
// retrieve the data
this._specimenService.getSpecimens().subscribe((data) => {
const specimens = [];
if (this.tree) {
//logic goes here...
//...
}
});
}
}