4

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() が含まれます。通常は言及されていないこのパターンの欠点は、マッピングする必要があることです。呼び出し元のコールバックでサービスで取得された生データ。コード内のこの 1 つの場所からこのサービスを呼び出すだけであれば、問題ないかもしれません。ただし、通常は、コード内のさまざまな場所からサービスを呼び出します。したがって、毎回、呼び出し元のコールバックでそのオブジェクトを何度もマップします。オブジェクトにフィールドを追加するとどうなるでしょうか? ここで、コード内のすべての呼び出し元を探して、マッピングを更新する必要があります。

だから、ここに私のアプローチがあります。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 か所で実行されます。そのため、コードの保守性が向上します。お役に立てれば。

4

1 に答える 1

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

追加情報として、onError および onComplete コールバックの戻り値が Rx で使用されているとは思いません (ドキュメントを見ると、これらのコールバックのシグネチャの戻り値は ですvoid)。

于 2016-03-08T18:13:05.583 に答える