Перехват изменений свойств службы в угловых компонентах - PullRequest
0 голосов
/ 09 февраля 2019

Не могли бы вы помочь с моей проблемой?Заранее извините за мой английский.Поэтому я пытаюсь научить Angular и написать простое приложение.Но у меня проблема с передачей реквизита от сервиса к компоненту.

Ситуация: у меня есть служба, которая отправляет запрос в API с помощью getWeather () и задает ответ в подпорке weatherCatalog .Но для правильной сборки URL он должен получить пользовательские координаты методами setUrl () и setPosition ()

@Injectable({
  providedIn: 'root'
})
export class WeatherService {
    key = 'dd6301427900459c863160646190201';
    weatherCatalog;
    queryString = '';

  constructor(private http: HttpClient) { }

  setUrl(position) {
    this.queryString = `http://api.worldweatheronline.com/premium/v1/weather.ashx?key=${this.key}&q=${position.coords.latitude},${position.coords.longitude}&num_of_days=14&tp=4&format=json`;

    this.getWeather()
  }

  getWeather() {
    this.http.get(this.queryString)
        .subscribe(
            res => this.weatherCatalog = res,
            err => console.error(err)
        );
  }

  setPosition() {
    navigator.geolocation.getCurrentPosition(this.setUrl.bind(this))
  }
}

Кроме того, у меня есть компонент, в котором я пытаюсь скопировать данные, передаваемые служебным запросом Object в свойстве компонента weather .Но есть моя проблема, конечно, она не работает.Я думаю, потому что в момент установки свойства в компоненте свойства в сервисе имеют неопределенное значение.Я пытался использовать Observable и другие вещи rxjs разными способами, но безрезультатно (мои руки от azz виноваты в этом, я полагаю).

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

  constructor(private weatherService: WeatherService) {
    this.weather = weatherService.weatherCatalog
  }

  ngOnInit() {
        this.weatherService.setPosition();
  }

}

Моя идея была - я получаю пользовательские координаты, и после этогоотправить запрос в API.Получите ответ и сохраните его в свойстве службы, после чего передайте его компоненту, где скопируйте его в свойство компонента.И если значение свойства в сервисе будет изменено - значение свойства в компоненте должно получить это изменение.

Это выглядит просто, но я действительно застрял.Буду очень признателен, если вы подскажете, как я не могу это осознать или где я могу прочитать об инструментах, которые мне помогают.

1 Ответ

0 голосов
/ 09 февраля 2019

Я бы сделал это так:

import { Component } from '@angular/core';
import { Observable, of } from 'rxjs';

import { WeatherService } from './weather.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  weather$: Observable<any>;

  constructor(private weatherService: WeatherService) {
  }

  ngOnInit() {}

  async getWeather() {
    try {
      const position  = await this.weatherService.getCurrentPosition();
      this.weather$ = this.weatherService.getWeather(position);
    } catch(error) {
      this.weather$ = of(`You'll not get the Geolocation Services to work in this mode. Try Clicking on the 'Open in New Window LIVE' button to see if that works for you!`);
    }
  }
}

В шаблоне компонента:

<code><button (click)="getWeather()">Get Weather</button>
<pre>
  {{ weather$ | async | json }}

А в Сервисе:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class WeatherService {
  key = 'dd6301427900459c863160646190201';
  weatherCatalog;

  constructor(private http: HttpClient) { }

  getWeather(position) {
    const { latitude, longitude } = position.coords;
    const queryString = `https://api.worldweatheronline.com/premium/v1/weather.ashx?key=${this.key}&q=${latitude},${longitude}&num_of_days=14&tp=4&format=json`;
    return this.http.get(queryString);
  }

  async getCurrentPosition() {
    return new Promise((resolve, reject) => {
      navigator.geolocation.getCurrentPosition(
        res => resolve(res),
        err => reject(err)
      );
    });
  }

}

Вот Рабочая демонстрация этой реализации.


Вот Образец StackBlitz для кода.

...