如何使用返回类型

时间:2016-03-02 18:56:42

标签: return-type observable typescript1.7 rxjs5

我在TypeScript中有一个Google地理编码服务。在获取给定地址的lat / long之后,我需要使用此方法返回“GoogleMap”类。

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

  

既不是空的也不是任何必须返回值的函数......

这是我的方法:

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调用将是异步的,并且流程应该继续到方法的底部,可能在响应返回数据之前。要返回“GoogleMap”,我是否需要等待此Observable?我该怎么做呢?

谢谢!

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

所以,这是我的方法。我们无法摆脱subscribe(),我们也不愿意。在这种情况下,我们的服务将返回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对象包装在“观察者”中。我们现在来看看来电者:

添加此属性:

private _gMapObservable: Observable<GoogleMap>;

呼叫者:

getLatLongs(streetAddress: string) {
     this._gMapObservable = this.geoService.getLatLongFromAddress(this.streetAddr);

     this._gMapObservable.subscribe((data)=>{
          this.googleMap = data;
     });
}

如果您注意到,呼叫者中没有映射!你只需要取回你的物体。所有复杂的映射逻辑都在一个地方的服务中完成。因此代码可维护性得到增强。希望这会有所帮助。

1 个答案:

答案 0 :(得分:0)

您的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),尽管我可能会弄错