Angular 6 - HttpClient在服务中保留订阅,但将结果传递给组件

时间:2018-05-28 16:25:06

标签: angular typescript angular6 angular-httpclient

我有一个preject包含一个服务(获取数据)和一个组件(显示它)。

我想在app.component.ts上将代码保持在最低限度。

在我的服务中:

:-1: error: An exception was triggered: 
Exception at 0x4015f6, code: 0x4000001f: Win32 x86 emulation subsystem breakpoint hit, flags=0x0.

并在我的app.component.ts中:

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

但是,当然,我需要得到结果并将其传递给我的组件,但这样的事情不会起作用:

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

所以,我的问题是,我该怎么做呢?或者是否真的建议在我的组件上调用subscribe而不是在服务中?

4 个答案:

答案 0 :(得分:4)

在新的 HttpClientModule 中,JSON是假设的默认值,不再需要使用res.json()显式解析

您可以告诉HttpClient响应的类型,使输出更容易,更明显。

可以使用类型参数
来完成响应的类型检查 创建一个接口

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

Http返回observable我们可以告诉HttpClient.getresponse作为Idata类型返回当我们使用http.get<Idata[]>(...)时,它会返回{的实例{1}}类型。
在您的服务中

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中获取Idata的实例

Observable<Idata[]>

另一种方法是使用 public data:Array<Idata>=[]; constructor(public service:ShareService) { this.service.getPosts().subscribe(value => { this.data=value; }); } 管道 async接受AsyncPipeobservable作为参数,调用promise或附加一个then处理程序,然后在将其传递给调用者之前等待异步结果。< / p>

subscribe

<强> HTML

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


LIVEDEMO

  

我的问题是,我该怎么做或者是否真的建议打电话   订阅我的组件而不是服务?

<强> It's Good Practice to Delegate complex component logic to services

  

来自 Angular样式指南
仅限制组件中的逻辑   视图所需的。应该委托所有其他逻辑   服务。

     

将可重用逻辑移动到服务并保持组件简单   专注于他们的预期目的。

     

为什么呢?放置在a中时,逻辑可以被多个组件重用   服务并通过功能公开。

     

为什么呢?服务中的逻辑可以更容易地在单元测试中被隔离,   而组件中的调用逻辑很容易被模拟。

     

为什么呢?删除依赖项并隐藏实现细节   成分

     

为什么呢?保持组件纤薄,修剪和聚焦。

订阅组件可让您与多个<div *ngFor="let item of (response|async)"> {{item.body}} </div> 共享一个http请求,如果您不这样做,则会违反 DRY Principle
<强>点:S  要为多个observers分享单个http请求,您需要 share 之类的内容 操作

observers
  

此运算符是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$ } } 的特化,它创建了一个   当观察者的数量从零变为1时的订阅   与所有后续观察者共享该订阅,直至该订阅   观察者数量返回零,此时订阅   处置。

答案 1 :(得分:1)

大!您可以尝试使用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)

试试看看是否有效!我希望有所帮助!

答案 2 :(得分:0)

如果您希望使用服务方法,必须返回如下的可观察响应:

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

答案 3 :(得分:-1)

你的component.ts应该是这样的。

您的服务没有问题,除了订阅应该是地图。

 this.myService.getPosts().subscribe((data) => {
         this.setMyData(data);
    });

    setMyData() {
        this.myData = data;
    }