Angular 6 - HttpClient 在服务中保持订阅但将结果传递给组件
Angular 6 - HttpClient Keeping subscribe in the service but passing the result to the component
我有一个包含服务(获取数据)和组件(显示数据)的项目。
我希望在 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();
}
所以,我的问题是,我该怎么做,或者真的建议在我的组件上而不是在服务中调用订阅?
如果您希望使用服务方法,必须 return 观察到这样的响应:
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);
});
你的component.ts应该是这样的
除了订阅应该是地图之外,您的服务没有问题。
this.myService.getPosts().subscribe((data) => {
this.setMyData(data);
});
setMyData() {
this.myData = data;
}
太棒了!您可以尝试使用 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)
试一试,看看是否有效!希望对您有所帮助!
在新的 HttpClientModule 中 JSON 是假定的默认值,不再需要使用 res.json()
显式解析
您可以告诉 HttpClient
响应的类型,使使用输出更容易和更明显。
响应的类型检查可以通过使用类型参数来完成
创建接口
export interface Idata{
userId:number;
Id:number;
title:string;
body:string;
}
Http
returns an observable
我们可以告诉 HttpClient.get
到 return response
作为 Idata 类型 当我们使用 http.get<Idata[]>(...)
然后它 return 是 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>
my question is, how can I do this or is it really recommended to call
subscribe on my component and not in the service?
It's Good Practice to Delegate complex component logic to services
From Angular Style Guide
Do limit logic in a component to only
that required for the view. All other logic should be delegated to
services.
Do move reusable logic to services and keep components simple and
focused on their intended purpose.
Why? Logic may be reused by multiple components when placed within a
service and exposed via a function.
Why? Logic in a service can more easily be isolated in a unit test,
while the calling logic in the component can be easily mocked.
Why? Removes dependencies and hides implementation details from the
component.
Why? Keeps the component slim, trim, and focused.
在组件中订阅可让您与多个 observers
共享一个 http
请求,否则您将违反 DRY Principle
P:S
要为多个 observers
共享单个 http
请求,您需要 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$
}
}
This operator is a specialization of publish
which creates a
subscription when the number of observers goes from zero to one, then
shares that subscription with all subsequent observers until the
number of observers returns to zero, at which point the subscription
is disposed.
我有一个包含服务(获取数据)和组件(显示数据)的项目。
我希望在 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();
}
所以,我的问题是,我该怎么做,或者真的建议在我的组件上而不是在服务中调用订阅?
如果您希望使用服务方法,必须 return 观察到这样的响应:
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);
});
你的component.ts应该是这样的
除了订阅应该是地图之外,您的服务没有问题。
this.myService.getPosts().subscribe((data) => {
this.setMyData(data);
});
setMyData() {
this.myData = data;
}
太棒了!您可以尝试使用 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)
试一试,看看是否有效!希望对您有所帮助!
在新的 HttpClientModule 中 JSON 是假定的默认值,不再需要使用 res.json()
显式解析
您可以告诉 HttpClient
响应的类型,使使用输出更容易和更明显。
响应的类型检查可以通过使用类型参数来完成
创建接口
export interface Idata{
userId:number;
Id:number;
title:string;
body:string;
}
Http
returns an observable
我们可以告诉 HttpClient.get
到 return response
作为 Idata 类型 当我们使用 http.get<Idata[]>(...)
然后它 return 是 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>
my question is, how can I do this or is it really recommended to call subscribe on my component and not in the service?
It's Good Practice to Delegate complex component logic to services
From Angular Style Guide
Do limit logic in a component to only that required for the view. All other logic should be delegated to services.Do move reusable logic to services and keep components simple and focused on their intended purpose.
Why? Logic may be reused by multiple components when placed within a service and exposed via a function.
Why? Logic in a service can more easily be isolated in a unit test, while the calling logic in the component can be easily mocked.
Why? Removes dependencies and hides implementation details from the component.
Why? Keeps the component slim, trim, and focused.
在组件中订阅可让您与多个 observers
共享一个 http
请求,否则您将违反 DRY Principle
P:S
要为多个 observers
共享单个 http
请求,您需要 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$
}
}
This operator is a specialization of
publish
which creates a subscription when the number of observers goes from zero to one, then shares that subscription with all subsequent observers until the number of observers returns to zero, at which point the subscription is disposed.