【问题标题】:Angular 5 Rxjs Service returns data "undefined" in NgOnInitAngular 5 Rxjs 服务在 NgOnInit 中返回数据“未定义”
【发布时间】:2019-01-10 05:57:29
【问题描述】:

我正在尝试将两个数据(数字)从一个组件传递到另一个组件。我可以发送数据并在我想使用它们的第二个组件上成功获取这些数据。但是,当我想在 NgOnInit 中使用它们时,我似乎无法使用它们。我将添加我的代码。有什么想法吗?

这是我的服务

    import { Injectable } from '@angular/core';
    import {Subject} from 'rxjs/Subject';

    @Injectable()
    export class StreetviewService {

    public StreetviewLatSubject= new Subject<any>();
    public StreetviewLonSubject= new Subject<any>();

    constructor() { }

    sendLatToStreetview(latt){
    this.StreetviewLatSubject.next(latt);
    console.log("I have the LAT streetview data: "+latt);
    }

    }

这里是第一个组件

    import { Component, OnInit} from '@angular/core';
    import {StreetviewService} from '../../services/streetview.service';

    @Component({
    selector: 'app-googlemaps',
    templateUrl: './googlemaps.component.html',
    styleUrls: ['./googlemaps.component.scss']
    })
    export class GooglemapsComponent implements OnInit {

    latt:number=0;

    constructor(public streetviewService:StreetviewService)
    {}

    // I am getting data from HTML selector

    onClickStreetview(lat){
    console.log(lat); 
    this.latt=lat;
    this.passStreetviewLat(this.latt);
    }

    passStreetviewLat(latt){
    this.streetviewService.sendLatToStreetview(latt);
    console.log("I have sent latt right now... "+latt);
    }

这是我的第二个组件

    import { Component, OnInit, ViewChild, Input, Inject, PLATFORM_ID, Output                         
    } from '@angular/core';
    import { MapsAPILoader } from '@agm/core';
    import { isPlatformBrowser } from '@angular/common';
    import {StreetviewService} from '../../services/streetview.service';
    import {DataService} from '../../services/data.service';

    @Component({
    selector: 'app-streetview',
    templateUrl: './streetview.component.html',
    styleUrls: ['./streetview.component.scss']
    })
    export class StreetviewComponent implements OnInit {
      @ViewChild('streetviewMap') streetviewMap: any;
      @ViewChild('streetviewPano') streetviewPano: any;
       public latt:number;
       public lonn:number;
       public lat:number;
       public lon:number;
      @Input() zoom: number = 11;
      @Input() heading: number = 34;
      @Input() pitch: number = 10;
      @Input() scrollwheel: boolean = false;
      newcenter:any=
      {lat:52.2296756,
        lon:21.012228700000037,
        zoom:14 }; 

      constructor( public streetviewService: StreetviewService,public                 
     dataService: DataService, @Inject(PLATFORM_ID) private platformId:         
     Object, private mapsAPILoader: MapsAPILoader ){

    this.streetviewService.StreetviewLatSubject.subscribe((receivedData)=>
    {this.latt=receivedData

    // Here we can see data !

    console.log("Right now we will see streetview Latitude: "+this.latt) })
      }

      ngOnInit() {

        console.log(this.latt) // Here shows that it is undefined !

        if(isPlatformBrowser(this.platformId)){
          this.mapsAPILoader.load().then(() => {
            let center = { lat:this.latt, lng: this.lonn };
            let map = new window['google'].maps.Map(this.streetviewMap.nativeElement, { center:center, zoom: this.zoom, scrollwheel: this.scrollwheel });
            let panorama = new window['google'].maps.StreetViewPanorama(
              this.streetviewPano.nativeElement, {
                position: center,
                pov: { heading: this.heading, pitch: this.pitch },
                scrollwheel: this.scrollwheel
              });
              map.setStreetView(panorama);
            });
          }


         }

    }

【问题讨论】:

  • 如果您创建了 stackblitz,那就太好了。模板内容也丢失了。

标签: angular rxjs angular5 subscribe


【解决方案1】:

这是异步请求的典型问题。而且您的服务订阅是一个异步请求。

从加载组件时的时间线来看,构造函数和 ngOnInit 的处理几乎是准同步的。因此,当服务订阅中的 console.log() 仍在等待返回值时,ngOnInit 中的 console.log() 已经触发了。而此时this.latt 仍然是未定义的。

    @Component({
    selector: 'app-streetview',
    templateUrl: './streetview.component.html',
    styleUrls: ['./streetview.component.scss']
    })
    export class StreetviewComponent implements OnInit {

      constructor(){
          this.streetviewService.StreetviewLatSubject.subscribe((receivedData)=>
      {
       this.latt=receivedData;
       console.log("I was received asynchronously: " + this.latt) })
      }

      ngOnInit() {
         console.log('I don't care when the streetviewService returns its value: ' + this.latt);
      }

如果你这样做,也会发生同样的事情:

 ngOnInit(): void {   
    this.streetviewService.StreetviewLatSubject.subscribe((receivedData)=>
    {
       this.latt=receivedData;
       console.log("I was received asynchronously: " + this.latt) })
    }

    console.log('I don't care when the streetviewService returns its value: ' + this.latt);
}

因此,如果您必须等待数据到达才能继续您的工作流程,请从服务订阅中调用后续方法,如下所示:

// inside constructor or ngOnInit
this.streetviewService.StreetviewLatSubject.subscribe((receivedData)=>
    {
       this.latt=receivedData;

       doSomething();
    }

...

private doSomething(): void {
   // do something with this.latt
}

【讨论】:

  • 请不要忘记将此答案标记为解决方案,如果它解决了您的问题或回答了您的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多