Класс читается после компонента - PullRequest
0 голосов
/ 06 ноября 2019

Я новичок в Angular.
Я пытаюсь сохранить данные в классе, чтобы прочитать их в компоненте. Я заметил, что до того, как класс полностью прочитан, компонент спешит с результатами, которые еще не были получены, затем выводит сообщение об ошибке:

Console output

Только позже он печатает значения правильно. Но только и исключительно в пределах subscribe, как видно из изображения.
Это мой класс:

import { Injectable } from '@angular/core';
import { WeatherForecastApiService } from '../weatherForecastApiService/weather-forecast-api.service';

@Injectable({
    providedIn: 'root',
})
export class WeatherClass {
    public weather: WeatherFeature;

    constructor(
        private wfas: WeatherForecastApiService,
    ) {
        this.wfas.getItalyWeatherData('Pisa').subscribe((response) => {
            const ks: string[] = ['name', 'main', 'temp'];
            this.weather = {
                cityName: response[ks[0]],
                degrees: response[ks[1]][ks[2]] - 273.15,
            }; 
            console.log('clean print', this.weather.cityName);
            console.log('clean print', this.weather.degrees);
        });
    }
    public showValues() {
        console.log('undefined print in component', this.weather.cityName);
        console.log('undefined print in component', this.weather.degrees);
    }
}

А это мой (преждевременный) компонент:

import { AfterViewInit, Component } from '@angular/core';
import { WeatherClass } from '../weatherObject/weather-class';

@Component({
    selector: 'app-weather-forecast',
    templateUrl: './weather-forecast.component.html',
    styleUrls: ['./weather-forecast.component.scss'],
})
export class WeatherForecastComponent implements AfterViewInit {
    constructor(
        private weather: WeatherClass,
    ) {}
    ngAfterViewInit() {
        this.weather.showValues();
    }
}

Я помню, что нечто подобное произошло со мной с помощью javascript, но контекст было легче решить (что он был асинхронным?).
Мне очень любопытно прояснить этот вопрос.

Ответы [ 2 ]

2 голосов
/ 06 ноября 2019

this.wfas.getItalyWeatherData является наблюдаемым и асинхронным, поэтому вполне вероятно, что ваш cityName и степень никогда не будут установлены к моменту вызова showValue(), даже если он есть в ngAfterViewInit.

AРешением было бы для вас иметь предмет в вашем WeatherClass, который вы могли бы прослушать (подписавшись на него) внутри вашего компонента WeatherForecastComponent. (рассмотрите BehaviorSubject, поскольку они содержат значение по умолчанию и позволяют получить значение при первой подписке)

@Injectable({
    providedIn: 'root',
})
export class WeatherClass {

    public weatherFeature = new BehaviorSubject<WeatherFeature>(undefined);

    constructor(
        private wfas: WeatherForecastApiService,
    ) {
        this.wfas.getItalyWeatherData('Pisa').subscribe((response) => {
            const ks: string[] = ['name', 'main', 'temp'];
            // This emits the new values for use to any subscribers.
            this.weatherFeature.next({
                cityName: response[ks[0]],
                degrees: response[ks[1]][ks[2]] - 273.15,
            }); 
        });
    }
}
@Component({
    selector: 'app-weather-forecast',
    templateUrl: './weather-forecast.component.html',
    styleUrls: ['./weather-forecast.component.scss'],
})
export class WeatherForecastComponent implements AfterViewInit {
    public weather: WeatherFeature;

    constructor(
        private weatherClass: WeatherClass,
    ) {}

    ngAfterViewInit() {
        // the subscription here will get the value or any future emitted values.
        this.weatherClass.weatherFeature.subscribe(
            (weatherFeature) => this.weather = weatherFeature
        );
    }
}

Так что в этом примере в вашем компоненте я добавил свойство для хранения значения, которое вы пытаетесьget.

в вашем классе погоды я добавил тему поведения, чтобы вы могли подписаться на нее, чтобы узнать, когда вы можете получить значение для использования.

Чтобы сохранить имена в чистом виде, я рекомендую переименоватьВаш WeatherClass to WeatherService :) Если у вас есть вопросы, ознакомьтесь с Руководством по угловым стилям. Это фантастический ресурс, чтобы привыкнуть к этой среде.

https://angular.io/guide/styleguide#service-names

1 голос
/ 06 ноября 2019

Проблема в том, что getItalyWeatherData не завершается до вызова showValues. Обычный подход будет выглядеть следующим образом:

WeatherClass ->

getItalyWeatherData() {
  return this.wfas.getItalyWeatherData('Pisa');
}

WeatherForecastComponent ->

ngOnInit() {
  this.weather.getItalyWeatherData().subscribe(res => {same code as the one you currently have});
}

Таким образом, в момент разрешения вызова APIданные будут отображены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...