Javascript RxJS使用第一个流的输出运行第二个流
我有一个服务,它决定了位置,它被写为可观察的Javascript RxJS使用第一个流的输出运行第二个流,javascript,angular,rxjs,observable,Javascript,Angular,Rxjs,Observable,我有一个服务,它决定了位置,它被写为可观察的 import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; const GEOLOCATION_ERRORS = { 'errors.location.unsupportedBrowser': 'Browser does not support location services', 'errors.location.permissio
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 }
];
从'@angular/core'导入{Injectable};
从“rxjs”导入{Observable};
常量地理位置错误={
'errors.location.unsupportedBrowser':'Browser不支持位置服务',
“errors.location.permissionDenied':“您已拒绝访问您的位置”,
“errors.location.positionUnavailable':“无法确定您的位置”,
'错误.位置.超时':'已达到服务超时'
};
@可注射()
导出类地理定位服务{
公共getLocation(opts):可观察{
返回可观察的。创建(观察者=>{
if(window.navigator&&window.navigator.geolocation){
window.navigator.geolocation.getCurrentPosition(
(职位)=>{
观察员:下一个(位置);
observer.complete();
},
(错误)=>{
开关(错误代码){
案例1:
observer.error(地理位置错误['ERRORS.location.permissionDenied');
打破
案例2:
观察者错误(地理位置错误['ERRORS.location.positionUnavailable']);
打破
案例3:
observer.error(GEOLOCATION_ERRORS['ERRORS.location.timeout']);
打破
}
},opts);
}否则{
observer.error(地理位置错误['ERRORS.location.unsupportedBrowser']);
}
});
}
}
导出变量GeolocationServiceInjectables:数组=[
{provide:GeolocationService,useClass:GeolocationService}
];
然后在我的HttpService中,我想用location服务的输出构造查询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 }
];
从'rxjs/Observable'导入{Observable};
从“@angular/core”导入{Injectable,injection};
从'@angular/Http'导入{Http,Response};
从“./location.service”导入{GeolocationService};
从“../weather item/weather item.model”导入{WeatherItem};
export const OpenWeatherMap_API_KEY:string='SOME_API_KEY';
export const OpenWeatherMap\u API\u URL:string='10〕http://api.openweathermap.org/data/2.5/forecast';
@可注射()
导出类HttpService{
构造函数(私有http:http,
私人地理定位:地理定位服务,
@注入(OpenWeatherMap_API_密钥)私有apiKey:string,
@Inject(OpenWeatherMap\uAPI\uURL)私有apiUrl:string){
}
prepairequiry():void{
this.geolocation.getLocation({enableHighAccurance:false,maximumAge:3})。订阅(
(职位)=>{
让参数:字符串=[
`纬度=${position.latitude}`,
`lon=${position.longitude}`,
`APPID=${this.apiKey}`,
].加入(“&”);
//返回`${this.apirl}?${params}`;
}
);
}
getWeather():可观察{
返回此.http.get(/*应该有url*/)
.map((响应:响应)=>{
return(response.json()).items.map(item=>{
康斯特市={
城市:item.city.name,
国家:item.city.country,
}
返回item.list.map(实体=>{
返回新的天气项目({
temp:entity.main.temp,
temMin:entity.main.temp_min,
temMax:entity.main.temp_max,
weatherCond:entity.weather.main,
description:entity.weather.description,
风速:entity.wind.speed,
图标:entity.weather.icon,
城市
})
})
})
})
}
}
导出变量HttpServiceInjectables:数组=[
{provide:HttpService,useClass:HttpService},
{提供:OpenWeatherMap\u API\u KEY,使用值:OpenWeatherMap\u API\u KEY},
{提供:OpenWeatherMap\uAPI\uURL,使用值:OpenWeatherMap\uAPI\uKey}
];
问题是如何在执行请求之前获取URL。我见过使用unsubscribe()的解决方案,但我认为它们都不太好。我考虑过merge(),但我不确定这是否是我真正想要的 您可能正在寻找RxJs的
mergeMap
操作符
mergeMap
所做的是自动订阅源可观察对象,然后让您在内部可观察对象中处理其结果,最后将输出平坦化
在本例中,您调用firstUrl
,并在第二次调用secondUrl
时使用从该请求获得的结果:
this.http.get(`{firstUrl}`)
.mergeMap(res => this.http.get(`{secondUrl}/{res.json()}`))
.subscribe(...)
我没有为你的代码做具体的说明,因为我不确定你到底想做什么。但我希望这会在路上帮助你 您可能正在寻找RxJs的
mergeMap
操作符
mergeMap
所做的是自动订阅源可观察对象,然后让您在内部可观察对象中处理其结果,最后将输出平坦化
在本例中,您调用firstUrl
,并在第二次调用secondUrl
时使用从该请求获得的结果:
this.http.get(`{firstUrl}`)
.mergeMap(res => this.http.get(`{secondUrl}/{res.json()}`))
.subscribe(...)
我没有为你的代码做具体的说明,因为我不确定你到底想做什么。但我希望这会在路上帮助你 这可以使用
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,
})
})
})
})
}
getWeather():可观察{
返回this.geolocation.getLocation({enableHighAccurance:false,maximumAge:3})
.map((位置)=>{