Return type 如何在返回类型为的TypeScript方法中从Observable返回

Return type 如何在返回类型为的TypeScript方法中从Observable返回,return-type,observable,typescript1.7,rxjs5,Return Type,Observable,Typescript1.7,Rxjs5,我有一个TypeScript的谷歌地理编码服务。我需要这个方法在获取给定地址的lat/long后返回一个“GoogleMap”类 我创建了一个TypeScript方法,它返回“GoogleMap”类型。但是,我得到了一份工作 既不是void也不是any的函数必须返回一个值 以下是我的方法: getLatLongFromAddress(streetAddress: string): GoogleMap { this.geoCodeURL = GOOGLE_GEOCODE_BASE_URL

我有一个TypeScript的谷歌地理编码服务。我需要这个方法在获取给定地址的lat/long后返回一个“GoogleMap”类

我创建了一个TypeScript方法,它返回“GoogleMap”类型。但是,我得到了一份工作

既不是void也不是any的函数必须返回一个值

以下是我的方法:

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调用将是异步的,并且流应该继续到方法的底部,可能在响应返回数据之前。要返回“谷歌地图”,我需要等待这个可观察到的吗?我该怎么做呢

谢谢

更新:2016年4月21日 我终于偶然发现了一种方法,我正在寻找一些满足感。我知道有很多开发者发帖要求提供“真正的”服务。他们希望将一个值传递给服务并获取一个对象。相反,许多答案并不能完全解决问题。简单的答案通常包括调用方的subscribe()。这种模式的缺点(通常未提及)是您必须将服务中检索到的原始数据映射到调用方的回调中。如果您只从代码中的这一个位置调用此服务,这可能没问题。但是,通常情况下,您将从代码中的不同位置调用该服务。因此,每次,您都会在调用方的回调中一次又一次地映射该对象。如果向对象添加一个字段会怎么样?现在,您必须查找代码中的所有调用者以更新映射

所以,这是我的方法。我们无法摆脱subscribe(),我们也不想离开。在这种情况下,我们的服务将返回一个
可观察的
,其中一个观察员拥有我们珍贵的货物。从调用者那里,我们将初始化一个变量,
Observable
,它将获得服务的
Observable
。接下来,我们将订阅此对象。最后,你得到你的“T”!谢谢你的服务

以我的例子,现在修改。注意这些变化。首先,我们的地理编码服务:

getLatLongFromAddress(streetAddress: string): Observable<GoogleMap> {
  ...
  return Observable.create(observer => {
      this.httpService
          .get(this.geoCodeURL)
          .subscribe((data) => {
              ...
              observer.next(this.googleMap);
              observer.complete();
          }

如果您注意到,调用方中没有映射!你只要拿回你的东西。所有复杂的映射逻辑都在一个位置的服务中完成。因此,代码的可维护性得到了增强。希望这能有所帮助。

您的
getLatLongFromAddress
的签名说它将返回一个GoogleMap,但是,不会返回任何内容(即当前函数的返回值将是未定义的)

您可以通过更新方法签名来消除此编译错误:

// 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回调返回值(查看文档,这些回调的签名返回值为
void
),尽管我可能弄错了。

我使用的是Angular 2和RxJS 5 beta。不确定这是否澄清了问题。我通常使用此结构从服务器获取数据。在“success”回调中,我返回一个googleMap对象。在.Net中,我将等待这个过程,直到服务返回lat和long,但我不确定如何使用RxJS执行此操作回调将返回googleMap对象,但是,getLatLongFromAddress方法不会返回任何导致编译错误的内容。在RXJS中,您可以订阅流而不是等待任务。Calvin,我认为您帮助澄清了这个问题。“等待”在多线程环境中非常方便。我们不是在这样的地方工作。我想我对打字脚本和可观察的东西有点太过雄心勃勃了。有很多服务的示例,其中服务“省略”了订阅功能。然后在调用者中,subscribe函数被附加到那里。感谢您阐明这个主题。
getLatLongs(streetAddress: string) {
     this._gMapObservable = this.geoService.getLatLongFromAddress(this.streetAddr);

     this._gMapObservable.subscribe((data)=>{
          this.googleMap = data;
     });
}
// 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;
        });
}