Angular4記賬webApp練手項目之一(利用angular-cli構(gòu)建Angular4.X項目)
Angular4記賬webApp練手項目之二(在angular4項目中使用Angular WeUI)
Angular4記賬webApp練手項目之三(在angular4項目中使用路由router)
Angular4記賬webApp練手項目之四(在Angular4項目中用echarts繪制圖表)
Angular4記賬webApp練手項目之五(Angular4項目中創(chuàng)建service(服務(wù))和使用http模塊)
前臺源碼
后臺源碼
說明:后臺代碼是用asp.net編寫的掉盅,和http://www.reibang.com/p/e6ed43227840這篇文章很像也拜。其中還包含了其他一些練手的東西。
前言
之前寫了那么多趾痘,不過都是靜態(tài)頁面÷現(xiàn)在使用http模塊與后端通信,變可以讓我們的應(yīng)用活起來扼脐。
我把后臺服務(wù)寫成了可跨域請求的webapi岸军,這樣在node上面調(diào)試起來就方便多了。
創(chuàng)建服務(wù)模塊
ng g service account
ng給我們創(chuàng)建的模塊account.service.ts瓦侮,內(nèi)容如下艰赞。
有關(guān)@Injectable和@Component,都是angular中的關(guān)鍵字或者關(guān)鍵注解肚吏。通過注解來表明js文件的類型方妖,以方便angular框架進(jìn)行調(diào)用。
@Component表示該js文件所導(dǎo)出的類是組件罚攀。
@Injectable表示該js文件所導(dǎo)出的文件是服務(wù)党觅,而服務(wù)是可以通過注入來創(chuàng)建的雌澄。
服務(wù)的注入,是angular中用來剝離controller和業(yè)務(wù)邏輯的方式杯瞻。
import { Injectable } from '@angular/core';
@Injectable()
export class AccountService {
constructor() { }
}
添加一個方法
getBillTypes() {
console.log('這是service里的方法');
}
引用服務(wù)
在accounting.component.ts里引用
import {AccountService} from '../account.service';
@NgModule({
providers: [
AccountService
],
})
推薦使用依賴注入的方式
constructor(private service: AccountService) {
service.getBillTypes(); // 調(diào)用方法
}
查看下效果镐牺,提示錯誤。
Unhandled Promise rejection: No provider for AccountService! ; Zone: angular ; Task: Promise.then ; Value:
原來是在app.module.ts 里面也要添加引用
import {AccountService} from './account.service';
providers: [AccountService],
這下就完成了簡單了例子魁莉。ng的編程風(fēng)格越來越像我們使用的c#睬涧,java等的編程風(fēng)格。當(dāng)然編程思想也是越來越和我們后臺開發(fā)相似了旗唁。
整理下我們的后臺接口
添加一個Model文件夾畦浓,在下面添加一個model.url.ts文件來存儲我們的接口信息
const host = 'http://127.0.0.1:8001';
export const Urls= {
GetBillTypes: host + '/api/bill/getbilltypes', // 獲取記賬類型
GetBills: host + '/api/bill/GetBills', // 獲取列表
GetCount: host + '/api/bill/GetCount', // 獲取統(tǒng)計信息
GetTotallCount: host + '/api/bill/GetTotallCount', // 獲取求和數(shù)據(jù)
AddBills: host + '/api/bill/AddBills', // 添加記賬信息
DeleteBill: host + '/api/bill/DeleteBill', // 刪除記賬信息
};
在我們的service中引入
import {Urls} from './Model/model.url';
整理方法
export class AccountService {
private urls = Urls;
constructor() { }
getBillTypes(): void {
console.log(this.urls.GetBillTypes);
}
GetBills(): void {
console.log(this.urls.GetBills);
}
GetCount(): void {
console.log(this.urls.GetCount);
}
GetTotallCount(): void {
console.log(this.urls.GetTotallCount);
}
AddBills(): void {
console.log(this.urls.AddBills);
}
DeleteBill(): void {
console.log(this.urls.DeleteBill);
}
}
使用http模塊
在我們的app.module.ts中已經(jīng)引入了
import { HttpModule } from '@angular/http';
我們要在account.service.ts中引入
import { Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';
構(gòu)造函數(shù)中注入依賴
constructor(private http: Http) { }
修改getBillTypes方法試試,看請求返回數(shù)據(jù)和http.get返回的是什么检疫。
getBillTypes() {
console.log(this.urls.GetBillTypes);
const data = this.http.get(this.urls.GetBillTypes)
.toPromise()
.then(response => console.log(response));
console.log(data);
}
http.get(url)(或者post put delete)讶请,訪問服務(wù)器以后會返回一個observation對象,事實上是observation<服務(wù)器返回值>屎媳。通過toPromise轉(zhuǎn)換成promise對象以后夺溢,就可以正常的使用then方法去處理返回值了。
通過promise的then方法剿牺,可以獲得到服務(wù)器的返回值企垦。個返回值都是json字符串,而在angular還是先按字符串處理晒来。調(diào)用字符串的.json()方法轉(zhuǎn)化為json數(shù)組或者json對象钞诡,繼續(xù)調(diào)用關(guān)鍵字as將json數(shù)組或者json對象轉(zhuǎn)化類,轉(zhuǎn)化的方式是屬性對應(yīng)湃崩。
因此我們修改方法荧降,在model文件夾下添加自定義的Result類型,
// 接口返回數(shù)據(jù)格式
export class Result {
error: any; // 錯誤時返回的信息
result: any; // 成功時返回的數(shù)據(jù)
success: boolean; // 是否成功
}
在account.service.ts中引入并修改方法
import {Result} from './Model/model.result';
getBillTypes(): Promise<Result> { // 獲取記賬類型
return this.http.get(this.urls.GetBillTypes)
.toPromise()
.then(response => response.json() as Result)
.catch(this.handleError);
}
在accounting.component.ts中修改調(diào)用的方法
constructor(private service: AccountService) {
service.getBillTypes().then(r => { console.log(r); });
}
這正是我們后臺返回的數(shù)據(jù)且是json格式的攒读。
這里我們用到了自定義類型Result的作用呢朵诫,看控制臺打印的數(shù)據(jù),對數(shù)據(jù)沒什么影響薄扁,但是對我寫代碼是有幫助的剪返。看下面:
對邓梅,會提示脱盲,如果使用了類型里沒有的字段,還會報錯日缨。這活生生把一個弱類型語言變成了強(qiáng)類型的钱反。當(dāng)然如果不喜歡,我們可以不用自定義類。把自定義的Result換成any即可面哥。
完善service
添加三個自定義類型
// 記賬類型的數(shù)據(jù)結(jié)構(gòu)
export class BillType {
name: string;
fontStyle: string;
id: number;
}
// 記賬的數(shù)據(jù)結(jié)構(gòu)
export class Bill {
id: number;
creationTime: string;
money: number;
name: string;
fontStyle: string;
BillTypeId: number;
}
要細(xì)分就太多了哎壳,大致分成這幾類吧,引入并完善我們的方法
export class AccountService {
private urls = Urls;
constructor(private http: Http) { }
getBillTypes(): Promise<Result> { // 獲取記賬類型
return this.get(this.urls.GetBillTypes);
}
GetBills(date, skipCount, user): Promise<Result> {
const d = new URLSearchParams();
d.set('date', date);
d.set('skipCount', skipCount);
d.set('user', user);
return this.get(this.urls.GetBills, d);
}
GetCount(date: string, type: number, user: string, GroupBy = 0): Promise<Result> {
const d = new URLSearchParams();
d.set('date', date);
d.set('type', type.toString());
d.set('user', user);
d.set('GroupBy', GroupBy.toString());
return this.get(this.urls.GetCount, d);
}
GetTotallCount(user): Promise<Result> {
return this.get(this.urls.GetTotallCount + '?user=' + user);
}
AddBills(data): Promise<Result> {
return this.post(this.urls.AddBill, data);
}
DeleteBill(data: number): Promise<Result> {
return this.post(this.urls.DeleteBill, data);
}
// 對get請求進(jìn)行封裝
private get(url: string, data: URLSearchParams = null): Promise<Result> {
return this.http.get(url, { search: data} )
.toPromise().then(r => r.json() as Result)
.catch(this.handleError);
}
// 對post請求進(jìn)行封裝
private post(url: string, data: any): Promise<Result> {
return this.http.post(url, data)
.toPromise().then(r => r.json() as Result)
.catch(this.handleError);
}
// 捕獲異常并輸出
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
最后完善修結(jié)果如下: