使用 Angular2 和 TypeScript 将 http 功能移动到它自己的服务中
Move http functionaity into its own Service with Angular2 and TypeScript
在过去的 4 年中,我愉快地使用 Angular1.* 工作,目前正在尝试自学 Angular2 和 TypeScript!无论如何,我有一个顶级组件创建了一个 属性,它派生自我在另一个 class 中创建的类型。使用我的组件,当 ngOnInit()
被调用时,我对我作为后端编写的虚假 REST 服务进行了 http
调用。现在,当使用 AngularJS 编写应用程序时,我会把我的 $http
任务放入一个服务中,并将它们注入我的控制器中……我想对我的组件做同样的事情。这是我没有激活服务代码的组件...注意评论
import {Component, OnInit} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {Home} from './components/home/home';
import {UserStatus} from './types/types.ts'; // this is why my UserStatus Type is kept
import {UserData} from './services/user-data/UserData.ts'; // here is where I wish to write my sevice to perform the http tasks...
import {Http, Headers} from 'angular2/http';
@Component({
selector: 'app', // <app></app>
providers: [...FORM_PROVIDERS],
directives: [...ROUTER_DIRECTIVES],
pipes: [],
styles: [require('./app.scss')],
template: require('./app.html')
})
export class App {
userStatus: UserStatus;
constructor(public http: Http) {
this.userStatus = new UserStatus();
}
ngOnInit() {
// I really want to put this code into a seperate class and provide it as a service...
var headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.get('/restservice/userstatus', {headers: headers})
.map((data: any) => data.json())
.subscribe(
(data: any) => {
this.userStatus = data;
},
err => console.log(err), // error
() => console.log('getUserStatus Complete') // complete
);
/* I'd like to factor the above into a service kept in a diffent file like so*/
/*
UserData.getUserStatus().then((resp) => {
this.userStatus = resp;
})
*/
}
}
现在这是我的类型...对于我的 userStatus
属性...
export class UserStatus {
constructor (
public firstName?: string,
public fullPersId?: number,
public goldUser?: boolean,
public hasProfileImage?: boolean,
public hideMoblieNavigationAndFooter?: boolean,
public persId?: string,
public profileName?: string,
public profilePicture?: string,
public showAds?: boolean,
public siteId?: number,
public url?: string,
public verified?: boolean,
public appOS?: any,
public formerName?: any
) {
this.firstName = firstName || '';
this.fullPersId = fullPersId || 0;
this.goldUser = goldUser || false;
this.hasProfileImage = hasProfileImage || false;
this.hideMoblieNavigationAndFooter = hideMoblieNavigationAndFooter || false;
this.persId = persId || '';
this.profileName = profileName || '';
this.profilePicture = profilePicture || '';
this.showAds = showAds || false;
this.siteId = siteId || 0;
this.url = url || '';
this.verified = verified || false;
this.appOS = appOS || null;
this.formerName = formerName || null;
}
}
现在我希望将我的组件的 http 功能放入一个 serperate 服务中...我开始编写以下代码(请不要笑,我真的是 Angular2 的新手)
import {Injectable} from 'angular2/core';
import {Http, Headers} from 'angular2/http';
import {UserStatus} from '../../types/types.ts';
@Injectable()
export class UserData {
constructor(public http:Http) {
}
getUserStatus(): any {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.get('/restservice/userstatus', {headers: headers})
.map((data: any) => data.json())
.subscribe(
(data: any) => {
return data;
},
err => console.log(err), // error
() => console.log('getUserStatus Complete') // complete
);
}
}
现在我希望我可以调用服务 getUserStatus()
方法来执行 HTTP 数据获取并在我的 App
组件中调用它(我正在使用 AngularJS 1.x promise 示例,但我知道我真的应该使用 observables...我只是不知道如何!)
ngOnInit() {
UserData.getUserStatus().then((resp) => {
this.userStatus = resp;
});
}
这显然是垃圾,我不知道我在做什么(examples/tutorials 对于 Angular2 到目前为止似乎不是那么好或实用)。有人可以告诉我如何连接服务然后在我的组件中正确调用它吗?
我喜欢这个问题,因为我也走上了同样的道路,不得不重构我的代码。
因此,现在使用 RxJs observables 的最佳实践不是 return 来自 http 请求的 .subscribe() 方法中的 json。只需将其映射并 return 即可。
你在那里所做的是从它拥有的所有额外信息中剥离它。
你应该return observable,它是 get() 的整个实现。
getUserStatus(): any {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.get('/restservice/userstatus', {headers: headers})
.map((data: any) => data.json())
.catch(this.handleError)
);
}
private handleError(error: Response) {
// in a real world app, we may send the server to some remote logging infrastructure
// instead of just logging it to the console
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
然后在您的组件端,您可以简单地订阅 observable
export class App {
public userStatus:any;
// Have to inject the UserData Service it into our component here.
constructor(public http: Http, private _userData: UserData ) {
}
ngOnInit() {
this._userData.getUserStatus()
.subscribe(
(status) => {
this.userStatus = status;
},
(err) => {
console.log(err);
},
()=>{console.log("User status complete")}
);
}
}
好吧,这是 angular2 中最好的话题之一,所以我来这里回答这个问题 ;)
所以根据问题来点
带有单独服务文件(代码)的 Http 请求
据我所知,这是为服务(http 请求)使用单独文件的最佳做法,我们通常在服务文件中执行 http 请求内容,然后订阅组件文件中的响应。我们还使用模态(打字稿用于您在问题中发布的类型检查)。您必须像这样更改代码才能通过单独的服务文件执行以下操作:
userStatus.ts:
import {Component, View} from 'angular2/core';
import {Http, Response, RequestOptions, Headers, Request, RequestMethod} from 'angular2/http';
import {UserStatus} from './types/types.ts'; // better to write here for type checking etc.....
@Component({
selector: 'app-service'
})
export class appService {
headers: Headers;
requestoptions: RequestOptions;
res: Response;
student_category_array: Array<UserStatus> = [];
constructor(private http: Http) { }
getUserStatus(url) {
this.headers = new Headers();
this.headers.append("Content-Type", 'application/json');
this.headers.append("Authorization", 'id_token or some thing else....')
this.requestoptions = new RequestOptions({
method: RequestMethod.Get,
url: url,
headers: this.headers
})
return this.http.request(new Request(this.requestoptions(url)))
.map(res => {
// DO YOUR STUFF HERE whihc you want to return to component or
return [{status: res.status, json: res.json()}]
})
}
}
and your component file should look like as following:
import {Component, OnInit} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {Home} from './components/home/home';
import {UserStatus} from './types/types.ts'; // this is why my UserStatus Type is kept
import {UserData} from './services/user-data/UserData.ts'; // here is where I wish to write my sevice to perform the http tasks...
import {Http, Headers} from 'angular2/http';
@Component({
selector: 'app', // <app></app>
providers: [...FORM_PROVIDERS,UserStatus], //better to import FORM_PROVIDERS and basic providers at the time of bootstrapin
directives: [...ROUTER_DIRECTIVES],
pipes: [],
styles: [require('./app.scss')],
template: require('./app.html')
})
export class App implements OnInit {
constructor(private userStatus:UserStatus){
}
ngOnInit(){
this.serviceCalled();
}
serviceCalled(){
userData.getUserStatus(url or path to json....)
.subscribe(res=>{
//get your data and CODE HERE....
console.log(res)
})
}
}
出于参考目的,您也可以为 Http request
阅读我的这些答案
希望它能帮助您并澄清与您的问题相关的一些要点!
在过去的 4 年中,我愉快地使用 Angular1.* 工作,目前正在尝试自学 Angular2 和 TypeScript!无论如何,我有一个顶级组件创建了一个 属性,它派生自我在另一个 class 中创建的类型。使用我的组件,当 ngOnInit()
被调用时,我对我作为后端编写的虚假 REST 服务进行了 http
调用。现在,当使用 AngularJS 编写应用程序时,我会把我的 $http
任务放入一个服务中,并将它们注入我的控制器中……我想对我的组件做同样的事情。这是我没有激活服务代码的组件...注意评论
import {Component, OnInit} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {Home} from './components/home/home';
import {UserStatus} from './types/types.ts'; // this is why my UserStatus Type is kept
import {UserData} from './services/user-data/UserData.ts'; // here is where I wish to write my sevice to perform the http tasks...
import {Http, Headers} from 'angular2/http';
@Component({
selector: 'app', // <app></app>
providers: [...FORM_PROVIDERS],
directives: [...ROUTER_DIRECTIVES],
pipes: [],
styles: [require('./app.scss')],
template: require('./app.html')
})
export class App {
userStatus: UserStatus;
constructor(public http: Http) {
this.userStatus = new UserStatus();
}
ngOnInit() {
// I really want to put this code into a seperate class and provide it as a service...
var headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.get('/restservice/userstatus', {headers: headers})
.map((data: any) => data.json())
.subscribe(
(data: any) => {
this.userStatus = data;
},
err => console.log(err), // error
() => console.log('getUserStatus Complete') // complete
);
/* I'd like to factor the above into a service kept in a diffent file like so*/
/*
UserData.getUserStatus().then((resp) => {
this.userStatus = resp;
})
*/
}
}
现在这是我的类型...对于我的 userStatus
属性...
export class UserStatus {
constructor (
public firstName?: string,
public fullPersId?: number,
public goldUser?: boolean,
public hasProfileImage?: boolean,
public hideMoblieNavigationAndFooter?: boolean,
public persId?: string,
public profileName?: string,
public profilePicture?: string,
public showAds?: boolean,
public siteId?: number,
public url?: string,
public verified?: boolean,
public appOS?: any,
public formerName?: any
) {
this.firstName = firstName || '';
this.fullPersId = fullPersId || 0;
this.goldUser = goldUser || false;
this.hasProfileImage = hasProfileImage || false;
this.hideMoblieNavigationAndFooter = hideMoblieNavigationAndFooter || false;
this.persId = persId || '';
this.profileName = profileName || '';
this.profilePicture = profilePicture || '';
this.showAds = showAds || false;
this.siteId = siteId || 0;
this.url = url || '';
this.verified = verified || false;
this.appOS = appOS || null;
this.formerName = formerName || null;
}
}
现在我希望将我的组件的 http 功能放入一个 serperate 服务中...我开始编写以下代码(请不要笑,我真的是 Angular2 的新手)
import {Injectable} from 'angular2/core';
import {Http, Headers} from 'angular2/http';
import {UserStatus} from '../../types/types.ts';
@Injectable()
export class UserData {
constructor(public http:Http) {
}
getUserStatus(): any {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.get('/restservice/userstatus', {headers: headers})
.map((data: any) => data.json())
.subscribe(
(data: any) => {
return data;
},
err => console.log(err), // error
() => console.log('getUserStatus Complete') // complete
);
}
}
现在我希望我可以调用服务 getUserStatus()
方法来执行 HTTP 数据获取并在我的 App
组件中调用它(我正在使用 AngularJS 1.x promise 示例,但我知道我真的应该使用 observables...我只是不知道如何!)
ngOnInit() {
UserData.getUserStatus().then((resp) => {
this.userStatus = resp;
});
}
这显然是垃圾,我不知道我在做什么(examples/tutorials 对于 Angular2 到目前为止似乎不是那么好或实用)。有人可以告诉我如何连接服务然后在我的组件中正确调用它吗?
我喜欢这个问题,因为我也走上了同样的道路,不得不重构我的代码。 因此,现在使用 RxJs observables 的最佳实践不是 return 来自 http 请求的 .subscribe() 方法中的 json。只需将其映射并 return 即可。 你在那里所做的是从它拥有的所有额外信息中剥离它。
你应该return observable,它是 get() 的整个实现。
getUserStatus(): any {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.get('/restservice/userstatus', {headers: headers})
.map((data: any) => data.json())
.catch(this.handleError)
);
}
private handleError(error: Response) {
// in a real world app, we may send the server to some remote logging infrastructure
// instead of just logging it to the console
console.error(error);
return Observable.throw(error.json().error || 'Server error');
}
然后在您的组件端,您可以简单地订阅 observable
export class App {
public userStatus:any;
// Have to inject the UserData Service it into our component here.
constructor(public http: Http, private _userData: UserData ) {
}
ngOnInit() {
this._userData.getUserStatus()
.subscribe(
(status) => {
this.userStatus = status;
},
(err) => {
console.log(err);
},
()=>{console.log("User status complete")}
);
}
}
好吧,这是 angular2 中最好的话题之一,所以我来这里回答这个问题 ;)
所以根据问题来点
带有单独服务文件(代码)的 Http 请求
据我所知,这是为服务(http 请求)使用单独文件的最佳做法,我们通常在服务文件中执行 http 请求内容,然后订阅组件文件中的响应。我们还使用模态(打字稿用于您在问题中发布的类型检查)。您必须像这样更改代码才能通过单独的服务文件执行以下操作:
userStatus.ts:
import {Component, View} from 'angular2/core';
import {Http, Response, RequestOptions, Headers, Request, RequestMethod} from 'angular2/http';
import {UserStatus} from './types/types.ts'; // better to write here for type checking etc.....
@Component({
selector: 'app-service'
})
export class appService {
headers: Headers;
requestoptions: RequestOptions;
res: Response;
student_category_array: Array<UserStatus> = [];
constructor(private http: Http) { }
getUserStatus(url) {
this.headers = new Headers();
this.headers.append("Content-Type", 'application/json');
this.headers.append("Authorization", 'id_token or some thing else....')
this.requestoptions = new RequestOptions({
method: RequestMethod.Get,
url: url,
headers: this.headers
})
return this.http.request(new Request(this.requestoptions(url)))
.map(res => {
// DO YOUR STUFF HERE whihc you want to return to component or
return [{status: res.status, json: res.json()}]
})
}
}
and your component file should look like as following:
import {Component, OnInit} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router';
import {Home} from './components/home/home';
import {UserStatus} from './types/types.ts'; // this is why my UserStatus Type is kept
import {UserData} from './services/user-data/UserData.ts'; // here is where I wish to write my sevice to perform the http tasks...
import {Http, Headers} from 'angular2/http';
@Component({
selector: 'app', // <app></app>
providers: [...FORM_PROVIDERS,UserStatus], //better to import FORM_PROVIDERS and basic providers at the time of bootstrapin
directives: [...ROUTER_DIRECTIVES],
pipes: [],
styles: [require('./app.scss')],
template: require('./app.html')
})
export class App implements OnInit {
constructor(private userStatus:UserStatus){
}
ngOnInit(){
this.serviceCalled();
}
serviceCalled(){
userData.getUserStatus(url or path to json....)
.subscribe(res=>{
//get your data and CODE HERE....
console.log(res)
})
}
}
出于参考目的,您也可以为 Http request
希望它能帮助您并澄清与您的问题相关的一些要点!