代码之家  ›  专栏  ›  技术社区  ›  Francis Ducharme

组件逻辑中异步检索数据的问题

  •  0
  • Francis Ducharme  · 技术社区  · 4 年前

    我调用了一个服务,该服务在启动任何组件之前从服务器检索数据(字符串,在UI中使用),问题是数据在组件的模板中可用,但在代码中不可用,这很奇怪。

    我把它放进去了 ngOnInit 我的主要 AppComponent

    ngOnInit() { 
        this.dataContractService.getUIStrings();
    }
    

    这确实是在任何其他组件之前调用的 ngOnInit 因此,字符串将(应该)对他们可用。

    在这里 getUIStrings 代码:

    async getUIStrings() {
        let url = "/datacontract/getuistrings";
        let promise = await this.http.get<APIResponse>(url).pipe(map(x => { return x.responsePayload })).toPromise<any>();
        this.globals.UIStrings = promise.strings; //
    }
    

    我把结果放在 globals 这是一种可注射的服务,注射到需要访问的组件中 UIStrings .

    以下是我如何使用它的示例

    export class DashboardComponent {
    
        constructor(
            public globals: Globals,
        ) { }
    
        dashboardMessage: string;
    
        ngOnInit() {
            if (condition) {
                this.dashboardMessage = this.globals.UIStrings["DashboardAdminDesc"];
            }
            else {
                this.dashboardMessage = this.globals.UIStrings["DashboardDesc"];
            }
    
        }
    
    }
    

    在代码中, UIString 是一个空数组,但在上述组件的模板中,它是填充的。

    {{globals.UIStrings["DashboardAdminDesc"]}}
    

    这行得通。我在这里做错了什么?

    0 回复  |  直到 4 年前
        1
  •  0
  •   micronyks    4 年前

    问题是,

    1. appcomponent's ngOnInit 将首先被调用,因此 getUIStrings 函数将被调用。它是 promise 最终将得到解决并将结果分配给 this.globals.UIStrings (假设promise需要5分钟才能解决)

    2. 当promise仍在处理中时, DashboardComponent 已加载并且 this.dashboardMessage undefined 作为 这是全球性的。UIString 还没有任何数据 .

    3. 在html中,如果你使用 {{globals.UIStrings["DashboardAdminDesc"]}} ,它会起作用的,因为在某个时间点 这是全球性的。UIString 当promise被解析时,将有数据。在HTML中, this.globals 是引用类型。因此,如果您从服务中更改它,它将直接在使用它的任何HTML中可用(而不是在 .ts 文件)

      但是 如果你使用 {{this.dashboardMessege}} ,它将永远存在 未定义 因为 dashboard's ngOnInit 在promise解析之前执行。


    解决方案

    我给你一些想法。由于代码没有经过测试,所以不要指望它能正常工作。我不碰 这是全球性的。UIString 在下面的代码片段中。您可以根据需要重构以下代码。

    注: 由于您的 dashboard component 在promise解析之前执行。因此,应用程序和应用程序之间没有同步;仪表板组件。

    global.service

      response = new Subject<any>();  // consider response is your globals.UIStrings
    
    
    async getUIStrings() {
        let url = "/datacontract/getuistrings";
        let promise = await this.http.get<APIResponse>(url).pipe(map(x => { return x.responsePayload })).toPromise<any>();
                
        this.response.next(promise.strings);                      // data will be emitted for here
    }
    

    仪表板组件

    export class DashboardComponent {
        dashboardMessage: string;
    
        constructor(
            public globals: Globals,
        ) { 
                  
                   this.globals.response.subscribe(data=>{     // data will be received here
    
                      if (condition) {
                         this.dashboardMessage = data["DashboardAdminDesc"];
                      }
                      else {
                         this.dashboardMessage = data["DashboardDesc"];
                      }
                      
                   })
         }
    }
    

    .html

      {{dashboardMessge}} will always output desire result 
              
    
    推荐文章