首页 > 解决方案 > Angular - 如何在加载组件之前等待提供者获取请求完成?

问题描述

我的程序使用了我的 player.ts 文件中使用的全局变量。我将此播放器文件导入侧边栏组件,现在应用程序错误。问题是应用程序在 player.ts 中完成获取请求之前正在加载侧边栏组件。我首先在我的 app.module 中初始化 player.ts 文件。如果没有,我可以提示应用程序在加载组件之前等待吗?我尝试使用 await javascript 关键字,但所有组件和导入的文件似乎都是从 app.moudle 异步加载的。

应用程序模块.ts

 import { Player } from './player';
 import { SidebarComponent } from './sidebar/sidebar.component';
 @NgModule({
   declarations: [
     AppComponent,
     SidebarComponent,
   ],
   imports: [
     BrowserModule,
     AppRoutingModule,
     HttpClientModule,
        ],
   providers: [Player],
   bootstrap: [AppComponent]
 })

 export class AppModule {

   constructor(private player: Player) { 
     console.log("first console.log yeee");
     this.processPlayer()
   }
   async processPlayer(){
     let tester1 = await this.player.loadPlayer();
   }
  }

sidebar.component.ts

 import { Component, OnInit } from '@angular/core';
 import { Router } from '@angular/router';
 import { Player } from '../player';

 @Component({
   selector: 'app-sidebar',
   templateUrl: './sidebar.component.html',
   styleUrls: ['./sidebar.component.css']
 })
 export class SidebarComponent implements OnInit {
   projects
   focussections
   constructor(private router: Router, private player: Player) { }

   ngOnInit() {
     //get all the project to list on sidebar
     this.projects = this.player.getAllProjects();
     this.focussections = this.player.getAllSections4Project(this.focusID);
   }

   navigate2CreateTaskQuicky(){
     let info = {typeID:0}
     this.router.navigate(['/createtask', JSON.stringify(info)]);

   } 

 }

播放器.ts

 @Injectable()
 export class Player  {
    player : any
   constructor(private http: HttpClient)  {
     this.ngOnInit();
   }

   async ngOnInit() {}

    loadPlayer(){
     return this.http.get(url)
     .toPromise()
     .then(
       res => { // Success
         this.player = res;
         console.log("the player is fully loaded");
         console.log(this.player);
       }
     );
   }

   getAllProjects(){
     return this.player.projects;
   }

   getAllSections4Project(focusID){
     let inboxSectionStack = [];
     if(this.player){
       for(let x = 0; x< this.player.sections.length; x++){ 
         if(this.player.sections[x].project == focusID ){
           inboxSectionStack.push(this.player.sections[x]);
          }
       }// loop through all tasks in player
   }
   return inboxSectionStack;
   }

标签: javascriptangular

解决方案


您必须使用APP_INITIALIZER提供程序。这是在AppComponent(和任何其他组件)呈现之前运行的服务:

应用模块:

providers: [
  Player,
  {
    provide: APP_INITIALIZER,
    useFactory: initApp,
    multi: true,
    deps: [ Player ]
  }
]

然后你就可以制作工厂了。确保工厂返回一个函数,该函数又返回一个Promise

export function initApp(player: Player) {
  return () => this.player.loadPlayer()
}

如果您不关心 AppComponent 是否被渲染,但您不希望路由被解析,您可以将initialNavigation路由器配置中的标志设置为 false,并使用 AppComponent 内部的服务来解析并路由到正确的路径


推荐阅读