如何使用 Return 类型从 TypeScript 方法中的 Observable Return
How to Return From Observable in TypeScript Method with Return Type
我在 TypeScript 中有一个 Google 地理编码服务。在为给定地址获取 lat/long 之后,我需要此方法 return a "GoogleMap" class。
我创建了一个 return 是 "GoogleMap" 类型的 TypeScript 方法。但是,我收到
function that is neither void nor any must return a value...
这是我的方法:
getLatLongFromAddress(streetAddress: string): GoogleMap {
this.geoCodeURL = GOOGLE_GEOCODE_BASE_URL + streetAddress +
"&key=" + GOOGLE_MAPS_API_KEY;
this.googleMap = new GoogleMap();
this.httpService
.get(this.geoCodeURL)
.subscribe((data) => {
this.googleMap.lat = data.results.geometry.location.lat;
this.googleMap.long = data.results.geometry.location.lng;
return this.googleMap;
},
(error) => {
console.error(this.geoCodeURL + ". " + error);
return Observable.throw("System encountered an error: " + error);
},
() => {
console.info("ok: " + this.geoCodeURL);
return this.googleMap;
});
}
我可以理解 http 调用将是异步的,流程应该继续到方法的底部,可能在响应 returns 数据之前。对于return一个"GoogleMap",我需要等待这个Observable吗?我该怎么做呢?
谢谢!
更新:2016 年 4 月 21 日
我终于偶然发现了一种让我感到满意的方法。我知道有许多开发人员发帖请求 "real" 服务。他们想向服务传递一个值并取回一个对象。相反,许多答案并没有完全解决问题。简单的答案通常包括调用方的 subscribe() 。这种模式的缺点(通常不被提及)是您必须 map 在调用者的回调中从服务中检索到的原始数据。如果您只从代码中的一个位置调用此服务,可能没问题。但是,通常情况下,您将从代码中的不同位置调用该服务。因此,每次,您都会在调用者的回调中一次又一次地映射该对象。如果给对象加一个字段呢?现在,您必须寻找代码中的所有调用方来更新映射。
所以,这是我的方法。我们无法摆脱 subscribe(),我们也不想。本着这种精神,我们的服务将 return 一个 Observable<T>
与一个拥有我们宝贵货物的观察员。从调用方,我们将初始化一个变量 Observable<T>
,它将获得服务的 Observable<T>
。接下来,我们将订阅这个对象。终于,你得到了你的"T"!从你的服务。
以我为例,现修改。注意这些变化。首先,我们的地理编码服务:
getLatLongFromAddress(streetAddress: string): Observable<GoogleMap> {
...
return Observable.create(observer => {
this.httpService
.get(this.geoCodeURL)
.subscribe((data) => {
...
observer.next(this.googleMap);
observer.complete();
}
因此,我们将 googleMap 对象包装在 "observer" 中。让我们看看调用者,现在:
添加此 属性:
private _gMapObservable: Observable<GoogleMap>;
来电者:
getLatLongs(streetAddress: string) {
this._gMapObservable = this.geoService.getLatLongFromAddress(this.streetAddr);
this._gMapObservable.subscribe((data)=>{
this.googleMap = data;
});
}
如果您注意到,调用者中没有映射!你只要把你的东西拿回来。所有复杂的映射逻辑都在服务中的一个地方完成。因此增强了代码的可维护性。希望这有帮助。
你的 getLatLongFromAddress
的签名说它将 return 一个 GoogleMap,但是,什么都没有 returned(即你的函数的 return 值,因为它代表,将是未定义的)。
您可以通过更新方法签名来消除此编译错误:
// Return type is actually void, because nothing is returned by this function.
getLatLongFromAddress(streetAddress: string): void {
this.geoCodeURL = GOOGLE_GEOCODE_BASE_URL + streetAddress +
"&key=" + GOOGLE_MAPS_API_KEY;
this.httpService
.get(this.geoCodeURL)
.subscribe((data) => {
this.googleMap = new GoogleMap();
this.googleMap.lat = data.results.geometry.location.lat;
this.googleMap.long = data.results.geometry.location.lng;
},
(error) => {
console.error(this.geoCodeURL + ". " + error);
return Observable.throw("System encountered an error: " + error);
},
() => {
console.info("ok: " + this.geoCodeURL);
return this.googleMap;
});
}
额外的花絮,我认为 Rx 没有使用 onError 和 onComplete 回调 return 值(查看文档,这些回调的签名具有 return 值 void
), 虽然我可能会弄错。
我在 TypeScript 中有一个 Google 地理编码服务。在为给定地址获取 lat/long 之后,我需要此方法 return a "GoogleMap" class。
我创建了一个 return 是 "GoogleMap" 类型的 TypeScript 方法。但是,我收到
function that is neither void nor any must return a value...
这是我的方法:
getLatLongFromAddress(streetAddress: string): GoogleMap {
this.geoCodeURL = GOOGLE_GEOCODE_BASE_URL + streetAddress +
"&key=" + GOOGLE_MAPS_API_KEY;
this.googleMap = new GoogleMap();
this.httpService
.get(this.geoCodeURL)
.subscribe((data) => {
this.googleMap.lat = data.results.geometry.location.lat;
this.googleMap.long = data.results.geometry.location.lng;
return this.googleMap;
},
(error) => {
console.error(this.geoCodeURL + ". " + error);
return Observable.throw("System encountered an error: " + error);
},
() => {
console.info("ok: " + this.geoCodeURL);
return this.googleMap;
});
}
我可以理解 http 调用将是异步的,流程应该继续到方法的底部,可能在响应 returns 数据之前。对于return一个"GoogleMap",我需要等待这个Observable吗?我该怎么做呢?
谢谢!
更新:2016 年 4 月 21 日 我终于偶然发现了一种让我感到满意的方法。我知道有许多开发人员发帖请求 "real" 服务。他们想向服务传递一个值并取回一个对象。相反,许多答案并没有完全解决问题。简单的答案通常包括调用方的 subscribe() 。这种模式的缺点(通常不被提及)是您必须 map 在调用者的回调中从服务中检索到的原始数据。如果您只从代码中的一个位置调用此服务,可能没问题。但是,通常情况下,您将从代码中的不同位置调用该服务。因此,每次,您都会在调用者的回调中一次又一次地映射该对象。如果给对象加一个字段呢?现在,您必须寻找代码中的所有调用方来更新映射。
所以,这是我的方法。我们无法摆脱 subscribe(),我们也不想。本着这种精神,我们的服务将 return 一个 Observable<T>
与一个拥有我们宝贵货物的观察员。从调用方,我们将初始化一个变量 Observable<T>
,它将获得服务的 Observable<T>
。接下来,我们将订阅这个对象。终于,你得到了你的"T"!从你的服务。
以我为例,现修改。注意这些变化。首先,我们的地理编码服务:
getLatLongFromAddress(streetAddress: string): Observable<GoogleMap> {
...
return Observable.create(observer => {
this.httpService
.get(this.geoCodeURL)
.subscribe((data) => {
...
observer.next(this.googleMap);
observer.complete();
}
因此,我们将 googleMap 对象包装在 "observer" 中。让我们看看调用者,现在:
添加此 属性:
private _gMapObservable: Observable<GoogleMap>;
来电者:
getLatLongs(streetAddress: string) {
this._gMapObservable = this.geoService.getLatLongFromAddress(this.streetAddr);
this._gMapObservable.subscribe((data)=>{
this.googleMap = data;
});
}
如果您注意到,调用者中没有映射!你只要把你的东西拿回来。所有复杂的映射逻辑都在服务中的一个地方完成。因此增强了代码的可维护性。希望这有帮助。
你的 getLatLongFromAddress
的签名说它将 return 一个 GoogleMap,但是,什么都没有 returned(即你的函数的 return 值,因为它代表,将是未定义的)。
您可以通过更新方法签名来消除此编译错误:
// Return type is actually void, because nothing is returned by this function.
getLatLongFromAddress(streetAddress: string): void {
this.geoCodeURL = GOOGLE_GEOCODE_BASE_URL + streetAddress +
"&key=" + GOOGLE_MAPS_API_KEY;
this.httpService
.get(this.geoCodeURL)
.subscribe((data) => {
this.googleMap = new GoogleMap();
this.googleMap.lat = data.results.geometry.location.lat;
this.googleMap.long = data.results.geometry.location.lng;
},
(error) => {
console.error(this.geoCodeURL + ". " + error);
return Observable.throw("System encountered an error: " + error);
},
() => {
console.info("ok: " + this.geoCodeURL);
return this.googleMap;
});
}
额外的花絮,我认为 Rx 没有使用 onError 和 onComplete 回调 return 值(查看文档,这些回调的签名具有 return 值 void
), 虽然我可能会弄错。