2017-02-28 103 views
0

我有一个服务,它决定了位置输出第2流,它写为可观察RxJS运行与第一流

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

const GEOLOCATION_ERRORS = { 
    'errors.location.unsupportedBrowser': 'Browser does not support location services', 
    'errors.location.permissionDenied': 'You have rejected access to your location', 
    'errors.location.positionUnavailable': 'Unable to determine your location', 
    'errors.location.timeout': 'Service timeout has been reached' 
}; 

@Injectable() 
export class GeolocationService { 
    public getLocation(opts): Observable<any> { 
     return Observable.create(observer => { 
      if (window.navigator && window.navigator.geolocation) { 
       window.navigator.geolocation.getCurrentPosition(
        (position) => { 
         observer.next(position); 
         observer.complete(); 
        }, 
        (error) => { 
         switch (error.code) { 
          case 1: 
           observer.error(GEOLOCATION_ERRORS['errors.location.permissionDenied']); 
           break; 
          case 2: 
           observer.error(GEOLOCATION_ERRORS['errors.location.positionUnavailable']); 
           break; 
          case 3: 
           observer.error(GEOLOCATION_ERRORS['errors.location.timeout']); 
           break; 
         } 
        }, opts); 
      } else { 
       observer.error(GEOLOCATION_ERRORS['errors.location.unsupportedBrowser']); 
      } 
     }); 
    } 
} 

export var GeolocationServiceInjectables: Array<any> = [ 
    { provide: GeolocationService, useClass: GeolocationService } 
]; 

然后在我的HttpService的我想构造查询URL与输出来自位置服务

import { Observable } from 'rxjs/Observable'; 
import { Injectable, Inject } from '@angular/core'; 
import { Http, Response } from '@angular/http'; 
import { GeolocationService } from './location.service'; 
import { WeatherItem } from '../weather-item/weather-item.model'; 

export const OpenWeatherMap_API_KEY: string = 'SOME_API_KEY'; 
export const OpenWeatherMap_API_URL: string = 'http://api.openweathermap.org/data/2.5/forecast'; 

@Injectable() 
export class HttpService { 
    constructor(private http: Http, 
     private geolocation: GeolocationService, 
     @Inject(OpenWeatherMap_API_KEY) private apiKey: string, 
     @Inject(OpenWeatherMap_API_URL) private apiUrl: string) { 
    } 

    prepaireQuery(): void { 
     this.geolocation.getLocation({ enableHighAccuracy: false, maximumAge: 3 }).subscribe(
      (position) => { 
       let params: string = [ 
        `lat=${position.latitude}`, 
        `lon=${position.longitude}`, 
        `APPID=${this.apiKey}`, 
       ].join('&'); 
       // return `${this.apiUrl}?${params}`; 
      } 
     ); 

    } 

    getWeather(): Observable<WeatherItem[]> { 
     return this.http.get(/*there should be the url*/) 
      .map((response: Response) => { 
       return (<any>response.json()).items.map(item => { 
        const city = { 
         city: item.city.name, 
         country: item.city.country, 
        } 
        return item.list.map(entity => { 
         return new WeatherItem({ 
          temp: entity.main.temp, 
          temMin: entity.main.temp_min, 
          temMax: entity.main.temp_max, 
          weatherCond: entity.weather.main, 
          description: entity.weather.description, 
          windSpeed: entity.wind.speed, 
          icon: entity.weather.icon, 
          city, 
         }) 
        }) 
       }) 
      }) 
    } 
} 
export var HttpServiceInjectables: Array<any> = [ 
    { provide: HttpService, useClass: HttpService }, 
    { provide: OpenWeatherMap_API_KEY, useValue: OpenWeatherMap_API_KEY }, 
    { provide: OpenWeatherMap_API_URL, useValue: OpenWeatherMap_API_KEY } 
]; 

问题是如何在请求前获取URL。我已经看到了取消订阅()的解决方案,但我认为它不太好。我想过合并(),但我不确定这是我真正想要的。

回答

1

您可能正在寻找RxJs的mergeMap运营商。

mergeMap所做的是自动订阅源observable,然后让您在其内部observable中处理其结果,然后最终展平输出。

在这个例子中,你叫firstUrl和使用结果,您从您的第二个呼叫请求得到secondUrl

this.http.get(`{firstUrl}`) 
    .mergeMap(res => this.http.get(`{secondUrl}/{res.json()}`)) 
    .subscribe(...) 

我还没有做出具体的它为您的代码,因为我不确定你想要做什么。但我希望这会帮助你在路上!

+0

谢谢))它的工作原理) –

1

这是可以做到用map/flatMap组合:

getWeather(): Observable<WeatherItem[]> { 
    return this.geolocation.getLocation({ enableHighAccuracy: false, maximumAge: 3 }) 
     .map((position) => { 
      let params: string = [ 
       `lat=${position.latitude}`, 
       `lon=${position.longitude}`, 
       `APPID=${this.apiKey}`, 
      ].join('&'); 
      return `${this.apiUrl}?${params}`; 
     }) 
     .flatMap(url => this.http.get(url) 
     .map((response: Response) => { 
      return (<any>response.json()).items.map(item => { 
       const city = { 
        city: item.city.name, 
        country: item.city.country, 
       } 
       return item.list.map(entity => { 
        return new WeatherItem({ 
         temp: entity.main.temp, 
         temMin: entity.main.temp_min, 
         temMax: entity.main.temp_max, 
         weatherCond: entity.weather.main, 
         description: entity.weather.description, 
         windSpeed: entity.wind.speed, 
         icon: entity.weather.icon, 
         city, 
        }) 
       }) 
      }) 
     }) 
} 
+0

只是说明; 'flatMap'被重命名为'mergeMap'。 'flatMap'仍然有效,因为它是'mergeMap'的别名。 –