web-dev-qa-db-ja.com

Angular 6-HttpClientサービスでサブスクライブし続けるが、結果をコンポーネントに渡す

サービス(データを取得)とコンポーネント(それを表示)を含むprejectがあります。

App.component.tsでコードを最小限に抑えたい。

私が持っているサービスでは:

getPosts() {
    return this.http.get('https://jsonplaceholder.typicode.com/posts', httpOptions).subscribe(
      result => {
        return result;
        this.theData = result;
      },
      error => {
        return error;
      }
    );
  }

そして私のapp.component.tsで:

 getPostsFromService() {
    this.myService.getPosts();
  }

しかし、もちろん、結果を取得してコンポーネントに渡す必要がありますが、次のようなものは機能しません。

myData;

  ...


  getPostsFromService() {
    this.myData = this.myService.getPosts();
  }

だから、私の質問は、どのようにこれを行うことができますか、サービスではなくコンポーネントでsubscribeを呼び出すことを本当にお勧めですか?

7
MarkHill2018

新規HttpClientModuleJSONはデフォルトと想定され、res.json()を使用して明示的に解析する必要はなくなりました

HttpClientに応答のタイプを伝えることで、出力の消費をより簡単かつ明確にすることができます。

応答の型チェックは、typeパラメーターを使用して実行できます
インターフェースを作成する

_export interface Idata{
  userId:number;
  Id:number;
  title:string;
  body:string;
}
_

Httpobservableを返し、http.get<Idata[]>(...)を使用するとresponseをIdata型として返すように_HttpClient.get_に伝えることができます。 _Observable<Idata[]>_タイプの.
サービスで

_import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {Observable} from 'rxjs';
import {Idata} from './Idata'
@Injectable()
export class ShareService {

    constructor(private httpc:HttpClient)
    {
    }

    public getPosts():Observable<Idata[]>
    {
        return this.httpc.get<Idata[]>('https://jsonplaceholder.typicode.com/posts');
    }
}
_

コンポーネントでsubscribeから_Observable<Idata[]>_にIdataのインスタンスを取得します

_  public data:Array<Idata>=[];
  constructor(public service:ShareService)
  {
     this.service.getPosts().subscribe(value => {
        this.data=value;
     });
  }
_

別の方法として、asyncパイプを使用するAsyncPipeが引数としてobservableまたはpromiseを受け入れ、subscribeを呼び出すか、thenハンドラをアタッチします次に、非同期の結果を待ってから呼び出し元に渡します。

_public response:Observable<Idata[]>;
constructor(public service:ShareService)
{
    this.response=this.service.getPosts();
}
_

[〜#〜] html [〜#〜]

_<div *ngFor="let item of (response|async)">
  {{item.body}}
</div>
_


[〜#〜] livedemo [〜#〜]

私の質問は、どのようにこれを行うことができますか、またはサービスではなくコンポーネントでsubscribeを呼び出すことを本当に推奨していますか?

複雑なコンポーネントロジックをサービスに委任するのは良い習慣です

FromAngular Style Guide
コンポーネントのロジックを、ビューに必要なロジックのみに制限します。他のすべてのロジックはサービスに委任する必要があります。

再利用可能なロジックをサービスに移動し、コンポーネントをシンプルにし、意図した目的に焦点を合わせてください。

どうして?ロジックは、サービス内に配置され、関数を介して公開されると、複数のコンポーネントによって再利用される場合があります。

どうして?サービスのロジックは単体テストでより簡単に分離できますが、コンポーネントの呼び出しロジックは簡単にモックできます。

どうして?依存関係を削除し、コンポーネントから実装の詳細を隠します。

どうして?コンポーネントのスリム化、トリム、フォーカスの維持。

Componentでサブスクライブすると、単一のhttpリクエストを複数のobserversと共有できます。そうしないと、DRY Principle
P:S複数のhttpに対する単一のobservers要求を共有するには、次のようなものが必要です。 share演算子。

_import {Observable} from 'rxjs';
import {share} from 'rxjs/operators'

export class dataService {

    public data$=Observable<Idata[]>
    constructor(http:HttpClient)
    {
        this.data$=this.http.get<Idata[]>('https://jsonplaceholder.typicode.com/posts').pipe(share());
    }
    public getPosts():Observable<Idata[]>
    {
        return this.data$
    }
}
_

この演算子はpublishの特殊化であり、オブザーバーの数が0から1になったときにサブスクリプションを作成し、オブザーバーの数がゼロに戻るまでサブスクリプションを後続のすべてのオブザーバーと共有します。処分した。

4
Vikas

すばらしいです! ObservableとAsyncを試すことができます! app.componentで

public posts: Observable<posts[]>
getPostsFromService() {
  this.posts = this.myService.getPosts();
}

そして、htmlに次のように記述します。

*ngFor="let post of posts | async"

そしてサービス

return this._http.get<posts>('https://jsonplaceholder.typicode.com/posts', httpOptions)

それを試して、動作するかどうかを確認してください!それがお役に立てば幸いです!

1
Chiien

サービスメソッドを使用する場合は、次のような監視可能な応答を返す必要があります。

public getPosts(): Observable<IPosts[]> {

    const data = {
      '$type' : 'ReadRequest',
      'query' : 'getPosts',
      'parameters' : {}
    };

    return this.http.post(null, data)
      .map(res => (<any>res)._body === '' ? {} : res.json().result)
      .catch(this.handleError);
  }

  private handleError(error: any): Promise<any> {
    return Promise.reject(error.message || 'Server error: ' + error);
  }

IPostsには、応答に応じたインターフェイスが記述されています。

任意のコンポーネントでこれを使用できます:

public posts: IPosts[] = [];
this.servicePosts.getPosts().subscribe(data => {
       this.posts = data; // Fill data from response to component variable this.post
          }, error => {
            console.log(error);
          });
0
OPV