【问题标题】:Http subscribe data not assigning to variableHttp订阅数据未分配给变量
【发布时间】:2019-07-19 23:06:54
【问题描述】:

我想从 api 获取数据并将其分配给我的变量。

在订阅中,我将数据分配给subscribe 中的变量和控制台记录的变量。一切正常,变量现在有了数据,但在subscribe 结束后,busDepotLocality 仍然是未定义的。试图设置超时等待,但没有

app.component.ts:

 busDepotLocality: BusDepotLocality;

 ngOnInit() {
     this.mapService
         .getBusDepotLocality()
         .subscribe((data: BusDepotLocality) => { 
           this.busDepotLocality = data;
           console.log(data); // Data is showing, no problem
           console.log(this.busDepotLocality); //Assignment passed, data is showing, no problem
         });

     console.log(this.busDepotLocality); // But after all busDepotLocality will be undefined

【问题讨论】:

  • 这是因为您混合了同步和异步调用。 subscribe 所做的只是设置一个侦听器,一旦 getBusDepotLocality 发出一个值,它就会执行 subscribe 中的内容。在设置该侦听器后,您立即执行控制台登录,最后一行被执行,并且由于尚未发出任何值但该值仍未设置。
  • 您的变量分配在订阅范围内。一旦 observable 发出一个值(即您的服务返回响应),就会执行 subscribe 中的代码。您首先到达最后一个console.log(),然后您会收到响应并执行订阅范围代码。要了解javascript中的async机制,你应该看看Philip Roberts wonderful expanation

标签: javascript angular typescript http


【解决方案1】:

试试这个:

async ngOnInit() {  // Step 1
   await this.mapService  // Step 2
         .getBusDepotLocality()
         .toPromise().then((data: BusDepotLocality) => { 
           this.busDepotLocality = data; // Step 3
           console.log(data); // Data is showing, no problem
           console.log(this.busDepotLocality); //Assignment passed, data is showing, no problem
         });

   console.log(this.busDepotLocality);  // Step 4
}

为了阐明我们如何在生命周期挂钩中使用 async-await,以下是步骤:

1) 在第 1 步中,我们使钩子异步,因此它不会妨碍/影响此生命周期钩子,因为我们在第 1 步不等待此方法调用,它将继续执行其他循环事件

2) 在第 2 步中,我们一直在等待,直到我们得到响应,await 之后的任何代码行都会等到我们得到异步调用的响应(“http”调用)

3) 在第 3 步中,我们得到响应。

4) 在第 4 步中,我们执行其余的语句。

PS : 由于这里我们要求在一切都完成并且您得到最终响应后执行语句,因此您需要将其转换为 Promise。

而且,如果你坚持考虑 observable,你可以在 html 中使用异步管道

\\ Component
  private data:Observable<any>;

 ngOnInit(){
    this.data=this.mapService.getBusDepotLocality();
  }

\\ HTML 

{{data|async}}

否则,您可以通过管道(点击())您的回复

【讨论】:

  • 只试一次..也让我在我的编辑答案中澄清
【解决方案2】:

您正在尝试记录尚未填充的内容。

作为证明,请尝试

busDepotLocality: BusDepotLocality;

 ngOnInit() {
     this.mapService
         .getBusDepotLocality()
         .subscribe((data: BusDepotLocality) => { 
           this.busDepotLocality = data;
           console.log(data); // Data is showing, no problem
           console.log(this.busDepotLocality); //Assignment passed, data is showing, no problem
         },(error) => {console.log(error)},() => {console.log(this.busDepotLocality); });


【讨论】:

    【解决方案3】:

    为了了解您遇到的问题,您需要对订阅有更好的了解。以我现在能想到的最简单的方式,将订阅视为 直播,这意味着只要您正在播放内容,您就可以访问数据。现在让我们将这个概念应用于您遇到的问题,我们有以下代码:

    busDepotLocality: BusDepotLocality;
    
     ngOnInit() {
         this.mapService
             .getBusDepotLocality()
             .subscribe((data: BusDepotLocality) => { 
               this.busDepotLocality = data;
               console.log(data); // Data is showing, no problem
               console.log(this.busDepotLocality); //Assignment passed, data is showing, no problem
             });
    
         console.log(this.busDepotLocality); // But after all busDepotLocality will be undefined
    

    您的评论实际上表明了我的观点 - 在订阅内可以访问数据,在订阅之外,无法分配数据。您可能希望映射数据,然后在您想要访问数据时订阅该变量。例如:

    busDepotLocality: BusDepotLocality;
    
     ngOnInit() {
         this.busDepotLocality = this.mapService
             .getBusDepotLocality()
             .pipe(map((data) => data));
         const results = this.busDepotLocality.subscribe(val => 
             console.log(val)
             //code goes here
         ); 
     }
    

    【讨论】:

      猜你喜欢
      • 2023-04-07
      • 2019-07-13
      • 1970-01-01
      • 1970-01-01
      • 2022-12-11
      • 1970-01-01
      • 2019-08-01
      • 2023-01-09
      • 1970-01-01
      相关资源
      最近更新 更多