wake-up-neo.com

Angular 6 - HttpClient Abonnieren im Dienst, Weiterleiten des Ergebnisses an die Komponente

Ich habe ein Vorprojekt, das einen Dienst enthält (der die Daten abruft) und eine Komponente (zeigt sie an).

Ich möchte, dass der Code auf der app.component.ts auf ein Minimum reduziert wird.

Im Dienst habe ich:

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

und in meiner app.component.ts:

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

Aber ich muss natürlich das Ergebnis bekommen und in meine Komponente übergeben, aber so etwas würde nicht funktionieren:

myData;

  ...


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

Meine Frage ist also, wie kann ich das tun, oder ist es wirklich empfehlenswert, einen Abonnement über meine Komponente und nicht über den Dienst anzurufen?

6
MarkHill2018

In neuen - HttpClientModule wird JSON als Standardwert verwendet und muss nicht mehr explizit mit res.json() analysiert werden.

Sie können HttpClient den Typ der Antwort angeben, um die Verwendung der Ausgabe einfacher und deutlicher zu machen.

Die Typprüfung der Antwort kann mit dem Typparameter erfolgen
Eine Schnittstelle erstellen

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

Http gibt eine observable zurück und wir können den HttpClient.get anweisen, response als Idata-Typ zurückzugeben. Wenn wir http.get<Idata[]>(...) verwenden, wird die Instanz von Observable<Idata[]>-Typ zurückgegeben. 
In Ihrem Dienst 
 

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

In Ihrer Komponente subscribe in Observable<Idata[]>, um eine Idata-Instanz abzurufen

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

Eine Alternative ist die Verwendung von async pipe AsyncPipe akzeptiert als Argument eine observable oder eine promise, ruft subscribe auf oder fügt einen Handler hinzu und wartet auf das asynchrone Ergebnis, bevor es an den Aufrufer übergeben wird.

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

meine Frage ist, wie kann ich das machen oder ist es wirklich empfehlenswert, anrufen. auf meiner Komponente abonnieren und nicht im Dienst?

Es ist empfehlenswert, komplexe Komponentenlogik an Dienste zu delegieren

Von Angular Style Guide
Begrenzen Sie die Logik in einer Komponente nur auf das für die Ansicht erforderlich. Alle andere Logik sollte an .__ delegiert werden. Dienstleistungen.

Verschieben Sie wiederverwendbare Logik in Dienste und halten Sie die Komponenten einfach und konzentriert sich auf ihren beabsichtigten Zweck.

Warum? Logik kann von mehreren Komponenten wiederverwendet werden, wenn sie in ein .__ eingefügt werden. Service und über eine Funktion angezeigt.

Warum? Die Logik in einem Dienst kann in einem Komponententest einfacher isoliert werden. während die aufrufende Logik in der Komponente leicht verspottet werden kann.

Warum? Entfernt Abhängigkeiten und blendet Implementierungsdetails aus der .__ aus. Komponente.

Warum? Hält die Komponente schlank, zurecht und konzentriert.

Durch das Abonnieren in Component können Sie eine einzige http-Anforderung mit mehreren observers teilen. Andernfalls verstoßen Sie gegen DRY Principle.
P: S Um eine einzige http-Anforderung für mehrere observers gemeinsam zu nutzen, benötigen Sie den Operator 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$
    }
}

Dieser Operator ist eine Spezialisierung von publish, die eine .__ erstellt. Abonnement, wenn die Anzahl der Beobachter von Null auf Eins geht, dann teilt diese Zeichnung mit allen nachfolgenden Beobachtern bis zum Die Anzahl der Beobachter wird auf Null zurückgesetzt. An diesem Punkt ist das Abonnement ist entsorgt.

4
Vikas

Großartig! Sie können es mit Observable und Async! In app.component versuchen

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

Und in HTML setzen Sie das:

*ngFor="let post of posts | async"

Und Service

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

Versuchen Sie das und sehen Sie, ob es funktioniert hat! Ich hoffe das hilft!

1
Chiien

Wenn Sie einen Service verwenden möchten, müssen Methoden wie folgt zurückgegeben werden:

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

Wo IPosts beschrieben wird, Schnittstelle entsprechend Ihrer Antwort.

Nachher in jeder Komponente können Sie Folgendes verwenden:

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