【问题标题】:How to Return From Observable in TypeScript Method with Return Type如何使用返回类型从 TypeScript 方法中的 Observable 返回
【发布时间】:2016-03-02 18:56:42
【问题描述】:

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

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

既不是 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 调用将是异步的,并且流程应该继续到方法的底部,可能在响应返回数据之前。要返回“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;
     });
}

如果您注意到,调用者中没有映射!你只是拿回你的对象。所有复杂的映射逻辑都在服务中的一个地方完成。因此增强了代码的可维护性。希望这会有所帮助。

【问题讨论】:

    标签: return-type observable typescript1.7 rxjs5


    【解决方案1】:

    您的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。不确定这是否能澄清事情。我通常使用这种结构从我的服务器获取数据。在“成功”回调中,我返回了一个 googleMap 对象。在 .Net 中,我会等待这个过程,直到服务返回纬度和经度,但我不确定你如何使用 RxJS 来做到这一点
    • 回调正在返回 googleMap 对象,但是,您的 getLatLongFromAddress 方法不会返回导致编译错误的任何内容。在 RXJS 中,您将订阅流而不是等待任务。
    • Calvin,我想你帮助澄清了这个问题。 “等待”在多线程环境中很方便。我们不是在这样的空间工作。我认为我对 Typescript 和 Observables 的能力有点过于雄心勃勃了。有很多服务“离开”订阅功能的服务示例。然后在调用者中,订阅函数被附加到那里。感谢您阐明这个主题。
    猜你喜欢
    • 2021-04-05
    • 2019-11-18
    • 2019-04-16
    • 1970-01-01
    • 1970-01-01
    • 2020-02-11
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多