在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()之后执行,但代码运行结果告诉情况并非如此。ngAfterViewInit()中的itemFound始终为"未定义"。

我试着把代码块从ngAfterViewInit()放到ngOnInit(),在promise调用之后,CCD_ 10将得到合适的值。

有人能解释一下哪里出了问题吗?是因为Promise调用是异步的吗?

根据Angular生命周期挂钩,ngAfterViewInit((应该在ngOnInit(

是.

但代码运行结果告诉情况并非如此。

没有。您不是在ngOnInit中分配列表,而是在promise回调中分配列表。一旦promise得到解决,就会调用该回调,但ngOnInit()不会等待它发生。(即使angular想等待,它也不能,因为angular不知道Promise对象存在,更不用说你已经向它添加了回调了——而且等待会冻结UI,所以angular不想等待(。

因此,如果你想等到两个承诺都得到解决,你必须询问承诺,而不是棱角分明的承诺。做到这一点的简单方法是:

ngOnInit() {
Promise.all([
this.localDataService.getData(),
this.remoteDataService.getData()
]).then(([list, data]) => {
// work with list and data
});
}

因为localDataService.getDataremoteDataService.getData都是异步的,所以不确定哪个先解析,ngOnInit完成时可能不会解析localDataService.getData

因此,即使您在ngOnInit完成后立即调用remoteDataService.getData,也不确定localDataService.getData是否已解析,而remoteDataService.getData将在何时解析。

您必须检查localDataService.getDataremoteDataService.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      
}
}
}

我用Rxjslib中的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
}
})
}
}
}

相关内容

  • 没有找到相关文章

最新更新