如何解决在 Angular 10 中的 ngOnInit() 之后完全执行某些逻辑
我想在 ngOnInit()
之后执行一些逻辑,因为我想将逻辑与页面呈现分离。
我想到了 Angular 生命周期钩子,所以我将逻辑放在 ngAfterViewInit()
中,但它似乎与 ngOnInit()
同时被调用。
代码示例:
export class SampleComponent implements OnInit,AfterViewInit{
list = [];
ngOnInit() {
this.localDataService.getData().then( res =>{ //Promise call
for (let o in res) {
this.list.push(res[o]) //the list get loaded
})
}
ngAfterViewInit() { // the intention is to process the list after it's loaded
this.remoteDataService.getData().then(res => {
for (let o in res) {
itemFound = this.list.find( (itemInList) => {return itemInList.id === res[o].id})
//and some code to manipulate the item found from list
itemFound = .... // but the itemFound is always 'undefined'
})
}
}
根据 Angular 生命周期钩子,ngAfterViewInit()
应该在 ngOnInit()
之后执行,但代码运行结果表明并非如此。 itemFound
中的 ngAfterViewInit()
始终为“未定义”。
在 promise 调用之后,我尝试将代码块从 ngAfterViewInit()
放到 ngOnInit()
,
itemFound
将获得正确的值。
谁能帮忙解释一下哪里出了问题?是不是因为 Promise 调用是异步的?
解决方法
因为 localDataService.getData
和 remoteDataService.getData
都是异步的,所以不确定哪个会先解决,localDataService.getData
可能在 ngOnInit
完成时还没有解决。
因此,即使您在 remoteDataService.getData
完成后立即调用 ngOnInit
,也不确定在 localDataService.getData
将被解析时 remoteDataService.getData
是否已解析。
您必须检查 localDataService.getData
和 remoteDataService.getData
是否都已解析。一种解决方案如下。
export class SampleComponent implements OnInit,AfterViewInit{
localList = [];
remoteList = [];
localListLoaded = false;
remoteListLoaded = false;
ngOnInit() {
this.localDataService.getData().then( res =>{ //Promise call
for (let o in res) {
this.localList.push(res[o]) //the list get loaded
}
localListLoaded = true;
manipulate();
});
this.remoteDataService.getData().then(res => {
for (let o in res) {
this.remoteList.push(res[o]);
}
remoteListLoaded = true;
manipulate();
}
}
manipulate() {
if (localListLoaded && remoteListLoaded) {
// some code stuff for remoteList and localList
}
}
}
,
根据 Angular 生命周期钩子,ngAfterViewInit() 应该在 ngOnInit() 之后执行,
是的。
但代码运行结果却相反。
它没有。您不是在 ngOnInit
中分配列表,而是在承诺回调中。一旦承诺得到解决,该回调将被调用,但 ngOnInit()
不会等待它发生。 (即使 angular 想要等待,它也不能,因为 angular 不知道 Promise 对象存在,更不用说您向它添加了回调 - 而且由于等待会冻结 UI,因此 angular 不想等待).
如果你想等到两个 promise 都解决了,那么你必须询问 promises,而不是 angular。这样做的简单方法是:
ngOnInit() {
Promise.all([
this.localDataService.getData(),this.remoteDataService.getData()
]).then(([list,data]) => {
// work with list and data
});
}
,
我通过 Rxjs 库中的 BehaviorSubject
实现了这一点,这基本上是一个可观察的模式。
重点是通知 ngAfterViewInit()
中的代码仅在列表数据准备就绪时启动。
代码示例:
export class SampleComponent implements OnInit,AfterViewInit{
list = [];
private listSub = new BehaviorSubject([]);
listSubObservab = this.listSub.asObservable();
ngOnInit() {
this.localDataService.getData().then( res =>{ //Promise call
for (let o in res) {
this.list.push(res[o]) //the list get loaded
}
this.listSub.next(this.list) //notify when list is ready
})
}
ngAfterViewInit() { // the intention is to process the list after it's loaded
this.listSubObservab.subscribe(listLoaded => { //observer here,only triggered by notify
this.remoteDataService.getData().then(res => {
for (let o in res) {
itemFound = listLoaded.find( (itemInList) => {return itemInList.id === res[o].id})
//and some code to manipulate the item found from list
itemFound = .... // Finally the itemFound has proper value
}
})
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。