如何在具有返回类型的TypeScript方法中从Observable返回 [英] How to Return From Observable in TypeScript Method with Return Type

查看:132
本文介绍了如何在具有返回类型的TypeScript方法中从Observable返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在TypeScript中拥有Google地理编码服务.在获取给定地址的经/纬度后,我需要此方法来返回"GoogleMap"类.

我创建了一个TypeScript方法,该方法返回"GoogleMap"类型.但是,我得到了

既不是无效函数也不是任何函数必须返回一个值...

这是我的方法:

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吗?我该怎么做呢?

谢谢!

更新:16/4/21 最后,我偶然发现了一种令我满意的方法.我知道有很多开发人员在乞求真正的"服务.他们想将一个值传递给服务并返回一个对象.相反,许多答案并不能完全解决问题.简单的答案通常在调用者方包括一个subscription().这种模式的缺点(通常不会提到)是您必须映射在调用者的回调中从服务中检索到的原始数据.如果仅从代码中的该位置调用此服务,则可能没问题.但是,通常,您将在代码的不同位置调用该服务.因此,每次您都会在调用者的回调中一次又一次地映射该对象.如果将字段添加到对象怎么办?现在,您必须寻找代码中的所有调用者以更新映射.

所以,这是我的方法.我们无法摆脱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;
     });
}

如果您注意到,则呼叫者中没有映射!你只要把你的东西拿回来.所有复杂的映射逻辑都在一处在服务中完成.因此,代码的可维护性得到了增强.希望这会有所帮助.

解决方案

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

I have a Google geocode service in TypeScript. I need this method to return a "GoogleMap" class, after it fetches the lat/long for a given address.

I created a TypeScript method that returns a "GoogleMap" type. But, I'm getting a

function that is neither void nor any must return a value...

Here's my method:

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;
        });
}

I can understand the http call will be async and the flow ought to continue to the bottom of the method, possibly before the response returns data. To return a "GoogleMap", do I need to await this Observable? How do I go about doing this?

Thanks!

UPDATE: 4/21/16 I finally stumbled on an approach that I'm finding some satisfaction. I know there's a number of posts from developers begging for a "real" service. They want to pass a value to the service and get an object back. Instead, many of the answers don't fully solve the problem. The simplistic answer usually includes a subscribe() on the caller's side. The down-side to this pattern, not usually mentioned, is that you're having to map the raw data retrieved in the service in the caller's callback. It might be ok, if you only called this service from this one location in your code. But, ordinarily, you'll be calling the service from different places in your code. So, everytime, you'll map that object again and again in your caller's callback. What if you add a field to the object? Now, you have to hunt for all the callers in your code to update the mapping.

So, here's my approach. We can't get away from subscribe(), and we don't want to. In that vein, our service will return an Observable<T> with an observer that has our precious cargo. From the caller, we'll initialize a variable, Observable<T>, and it will get the service's Observable<T>. Next, we'll subscribe to this object. Finally, you get your "T"! from your service.

Take my example, now modified. Take note of the changes. First, our geocoding service:

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

So, we're wrapping the googleMap object inside the "observer". Let's look at the caller, now:

Add this property:

private _gMapObservable: Observable<GoogleMap>;

Caller:

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

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

If you notice, there's no mapping in the caller! you just get your object back. All the complex mapping logic is done in the service in one place. So code maintainability is enhanced. Hope this helps.

解决方案

Your getLatLongFromAddress's signature says it will return a GoogleMap, however, nothing is ever returned (ie the return value of your function, as it stands, will be undefined).

You can get rid of this compilation error by updating your method signature:

// 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;
        });
}

Additional tidbit, I don't think the onError and onComplete callback return values are used by Rx (looking at the documentation, the signature for these callbacks has a return value of void), although I could be mistaken.

这篇关于如何在具有返回类型的TypeScript方法中从Observable返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆