typescript Angular 6 - HttpClient 保持订阅服务但将结果传递给组件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/50570340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 6 - HttpClient Keeping subscribe in the service but passing the result to the component
提问by
I have a preject which contains a service (which gets the data) and a component (displays it).
我有一个包含服务(获取数据)和组件(显示它)的项目。
I would like the keep the code to the minimum on the app.component.ts.
我希望将 app.component.ts 上的代码保持在最低限度。
In the service I have:
在服务中,我有:
getPosts() {
return this.http.get('https://jsonplaceholder.typicode.com/posts', httpOptions).subscribe(
result => {
return result;
this.theData = result;
},
error => {
return error;
}
);
}
and in my app.component.ts:
在我的 app.component.ts 中:
getPostsFromService() {
this.myService.getPosts();
}
But of course, I need to get the result and pass it into my component but something like this wouldn't work:
但是,当然,我需要获取结果并将其传递到我的组件中,但是这样的事情是行不通的:
myData;
...
getPostsFromService() {
this.myData = this.myService.getPosts();
}
So, my question is, how can I do this or is it really recommended to call subscribe on my component and not in the service?
所以,我的问题是,我该怎么做,还是真的建议在我的组件上调用 subscribe 而不是在服务中调用?
采纳答案by Vikas
In new HttpClientModuleJSON is an assumed default and no longer needs to be explicitly parsed using res.json()
在新的HttpClientModule 中,JSON 是假定的默认值,不再需要使用显式解析res.json()
You can tell HttpClient
the type of the response to make consuming the output easier and more obvious.
您可以告诉HttpClient
响应的类型,以便更轻松、更明显地使用输出。
Type checking of response can be done by using the type parameter
Create an Interface
响应的类型检查可以通过使用类型参数
Create an Interface来完成
export interface Idata{
userId:number;
Id:number;
title:string;
body:string;
}
Http
returns an observable
and We can tell the HttpClient.get
to return response
as Idata type When we use http.get<Idata[]>(...)
then it returns the instance of Observable<Idata[]>
type.
In your service
Http
返回一个observable
and 我们可以告诉HttpClient.get
返回response
为 Idata 类型 当我们使用http.get<Idata[]>(...)
then 它返回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');
}
}
In your component subscribe
to Observable<Idata[]>
to get instance of Idata
在您的组件subscribe
中Observable<Idata[]>
获取 Idata 的实例
public data:Array<Idata>=[];
constructor(public service:ShareService)
{
this.service.getPosts().subscribe(value => {
this.data=value;
});
}
An alternative is Using async
pipe
AsyncPipe
accepts as an argument an observable
or a promise
, calls subscribe
or attaches a then handler, then waits for the asynchronous result before passing it through to the caller.
另一种方法是使用async
管道
AsyncPipe
接受 anobservable
或 a作为参数promise
,调用subscribe
或附加 then 处理程序,然后在将异步结果传递给调用者之前等待异步结果。
public response:Observable<Idata[]>;
constructor(public service:ShareService)
{
this.response=this.service.getPosts();
}
HTML
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?
我的问题是,我该怎么做,还是真的建议在我的组件上调用 subscribe 而不是在服务中?
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.
来自Angular Style Guide
将组件中的逻辑限制为视图所需的逻辑。所有其他逻辑都应该委托给服务。务必将可重用逻辑移至服务并保持组件简单并专注于其预期目的。
为什么?当逻辑被放置在一个服务中并通过一个函数公开时,它可以被多个组件重用。
为什么?在单元测试中可以更轻松地隔离服务中的逻辑,而可以轻松模拟组件中的调用逻辑。
为什么?删除依赖项并隐藏组件的实现细节。
为什么?保持组件纤薄、修剪和集中。
Subscribing in Component lets you share a single http
request with multiple observers
, if you don't do so you would be violating DRY Principle
P:STo share a single http
request for multiple observers
, you need something like the shareoperator.
在 Component 中订阅允许您http
与多个共享单个请求observers
,如果您不这样做,您将违反DRY 原则
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$
}
}
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.
该运算符是一种特殊化,
publish
当观察者的数量从零变为 1 时,它会创建一个订阅,然后与所有后续观察者共享该订阅,直到观察者的数量归零,此时订阅将被处理。
回答by Chiien
Great! You can try with Observable and Async! In app.component
伟大的!您可以尝试使用 Observable 和 Async!在 app.component
public posts: Observable<posts[]>
getPostsFromService() {
this.posts = this.myService.getPosts();
}
And in html, you put that:
在 html 中,您输入:
*ngFor="let post of posts | async"
And service
和服务
return this._http.get<posts>('https://jsonplaceholder.typicode.com/posts', httpOptions)
Try that and see if worked! I hope that helps!
试试看,看看是否有效!我希望这有帮助!
回答by OPV
If you desire to use a service methods must return observable response like this:
如果您希望使用服务方法,则必须像这样返回可观察的响应:
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);
}
Where IPosts
is described Interface according your response.
IPosts
根据您的回复描述的接口在哪里。
After in any component you can use this:
在任何组件之后,您都可以使用它:
public posts: IPosts[] = [];
this.servicePosts.getPosts().subscribe(data => {
this.posts = data; // Fill data from response to component variable this.post
}, error => {
console.log(error);
});
回答by Padmapriya Vishnuvardhan
Your component.ts should be like this.
你的 component.ts 应该是这样的。
There is no issue in your service except subscribe should be map.
除了订阅应该是地图之外,您的服务没有问题。
this.myService.getPosts().subscribe((data) => {
this.setMyData(data);
});
setMyData() {
this.myData = data;
}