說明會有哪些常見的服務是所有組件都會用的。
開發過程中有幾種服務是必然用到的。
-src
|-app
|-app.component.css
|-app.component.html
|-app.component.ts
|-app.module.ts
|-service
|-logger.service.ts
|-web.service.ts
|-data.service.ts
|-user.service.ts
|-login.service.ts
實務上在接後端 API 的時候,
如果 request 有誤或是 Database 撈出來的 response 不符合預期,
在傳送給前端時會標註 errorcode
,
並有文件註明 errorcode 的各個編號含義。
但目前使用 json-server,
所以會在模擬後端回傳值收到後再包一層errorcode
。
data.service.ts
:import { Injectable } from "@angular/core";
import { Observable } from "rxjs/internal/Observable";
import { map } from "rxjs/operators";
import { WebService } from "./web.service";
import { ApiUrl } from "../config/config";
import { IModel, IUser } from "../model/data";
import { IData, IPage } from "../model/base";
import { Md5 } from "ts-md5";
export interface IFilter {
key: string;
val: string | number;
}
@Injectable({
providedIn: "root"
})
export class DataService {
apiUrl = ApiUrl;
constructor(private webService: WebService) {}
private setUrl(position: string, filters?: IFilter[], id?: number): string {
let url = `${this.apiUrl}/${position}/`;
if (!!id) {
url += `${id}`;
}
if (!!filters && !!filters.length) {
url += `?`;
filters.forEach((filter: IFilter, index: number) => {
if (!!index) {
url += `&&`;
}
url += `${filter.key}=${filter.val}`;
});
}
return url;
}
connect(token: string): Observable<IData> {
let url = this.setUrl("admins", [
{ key: "token", val: token },
{ key: "_embed", val: "holds" }
]);
return this.webService.getF(url).pipe(
map((res: IModel[]) => {
let errocode = 0;
if (!res || !res.length) {
errocode = 2;
}
if (!!res[0]) {
let user = <IUser>res[0];
if (user.status != 1) {
errocode = 3;
}
}
this.webService.setHeaders(token);
return <IData>{
res: res,
errorcode: errocode
};
})
);
}
resData(res: IModel[] | IModel, errocode: number): IData {
return <IData>{
res: res,
errorcode: errocode
};
}
getData(position: string, id?: number, filters?: IFilter[], pageObj?: IPage): Observable<IData> {
let url = this.setUrl(position, filters, id);
return this.webService.getF(url).pipe(
map((res: IModel[]) => {
let errocode = 0;
if (!!pageObj) {
pageObj.length = res.length;
res["pageObj"] = pageObj;
res = this.rangeData(res, pageObj);
}
return this.resData(res, errocode);
})
);
}
insertOne(position: string, obj: IModel): Observable<IData> {
let url = this.setUrl(position);
return this.webService.postF(url, obj).pipe(
map((res: IModel) => {
let errocode = 0;
if (!res || !res.id) {
errocode = 4;
}
return this.resData(res, errocode);
})
);
}
updateOne(position: string, obj: IModel, id: number): Observable<IData> {
let url = this.setUrl(position, null, id);
return this.webService.patchF(url, obj).pipe(
map((res: IModel) => {
let errocode = 0;
if (!res) {
errocode = 5;
}
return this.resData(res, errocode);
})
);
}
deleteOne(position: string, id: number): Observable<IData> {
let url = this.setUrl(position, null, id);
return this.webService.delF(url).pipe(
map((res: IModel) => {
let errocode = 0;
if (Object.keys(res).length !== 0) {
errocode = 6;
}
return this.resData(res, errocode);
})
);
}
//加上新增或是更新日期
checkData(obj: IModel, operatorId: number, isInsert = true): IModel {
let insert = <IModel>{
insertBy: operatorId,
inserted: new Date().getTime()
};
let update = <IModel>{
updateBy: operatorId,
updated: new Date().getTime()
};
if (isInsert) {
obj = { ...obj, ...insert, ...update };
} else {
//update
obj = { ...obj, ...update };
}
return obj;
}
rangeData(obj: IModel[], pageObj: IPage): IModel[] {
let start = pageObj.pageIndex * pageObj.pageSize;
let end = start + pageObj.pageSize;
if (pageObj.length < end) {
end = pageObj.length;
}
return obj.slice(start, end);
}
makeToken(account: string): string {
return <string>Md5.hashStr(`${account}`);
}
}
專案內使用的加密是
ts-md5
https://github.com/cotag/ts-md5
setUrl()
:組合url。不管是使用哪種 Http 的請求方法,
都必須要指定所需的 url。
url 以?
來區分前後:?
前面就是需要資料的指定位置
如:http://localhost:3000/customers/
?
後面就是需要資料的篩選或是關聯其他表
如:http://localhost:3000/admins/?_embed=holds
--
connect(token)
:與後端連接。流程上後台登入頁,管理者輸入帳號密碼後,
此時後端會回傳 token,
然後進入後台主頁時,會再把 token 送到後端,
驗證身份訊息來得到後台相關資料。
可能有人會想說,為什麼 token 送回來還要再送過去?
因一開始登入的帳號密碼送出後,後端會有個規則依據此帳號密碼來
形成一組 token 並加上有效期間,並傳回去給前端。
後續的請求包含需要此登入者身分的請求,
都需要夾帶著 token 送過去,
後端會在回應請求前,確定 token 有效,
才會去撈 Database 的資料再回傳。
不少後端實作其實是判斷帳號密碼成功後直接形成 token,
以及此登入者的身份都一次包好送回去。
--
CRUD的function
--
//model/base.ts
export interface IData {
res: IModel | IModel[];
errorcode: number;
}
https://stackblitz.com/edit/ngcms-service