【问题标题】:Execute certain logic exactly after ngOnInit() in Angular 10在 Angular 10 中的 ngOnInit() 之后执行某些逻辑
【发布时间】:2021-06-25 04:26:20
【问题描述】:

我想在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 调用之后, itemFound 将获得适当的价值。

谁能帮忙解释哪里出错了?是不是因为 Promise 调用是异步的?

【问题讨论】:

  • 为什么不创建一个简单的函数并在 getData() 承诺中调用它?
  • 我所做的和你提到的完全一样,但我发现remoteDataService.getData() 的承诺会显着影响页面渲染速度,因为它是一个远程调用并且需要很多时间。这就是我想将它们解耦的原因。

标签: angular promise sequence angular-lifecycle-hooks


【解决方案1】:

因为localDataService.getDataremoteDataService.getData都是异步的,所以不确定哪个会先解决,localDataService.getData可能在ngOnInit完成的时候还没有解决。

因此,即使您在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      
    }
  }

}

【讨论】:

  • 我阅读了您和 Meriton 的 cmets,实际上您说的是同样的事情,这也是正确的 - Promise 调用的时间已解决。但是我真的很想在视图初始化之后进行远程调用,这样就不会导致延迟。您的解决方案引发了另一个想法,即变量的侦听器。谢谢!
【解决方案2】:

根据 Angular 生命周期钩子,ngAfterViewInit() 应该在 ngOnInit() 之后执行,

是的。

但代码运行结果另有说明。

它没有。您不是在ngOnInit 中分配列表,而是在承诺回调中分配列表。一旦承诺得到解决,该回调将被调用,但ngOnInit() 不会等待这种情况发生。 (即使 Angular 想要等待,它也不能等待,因为 Angular 不知道 Promise 对象存在,更不用说您已经向它添加了回调 - 因为等待会冻结 UI,所以 Angular 不想等待)。

如果你想等到两个 Promise 都解决了,你必须问 Promise,而不是 Angular。简单的方法是:

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

【讨论】:

    【解决方案3】:

    我通过 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
    
           }
          })
    
        }
     }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-12
      • 1970-01-01
      • 2019-07-14
      • 2018-12-08
      • 2019-01-27
      • 2017-11-03
      相关资源
      最近更新 更多