zoukankan      html  css  js  c++  java
  • Angular4记账webApp练手项目之五(Angular4项目中创建service(服务)和使用http模块)

    前言

    之前写了那么多,不过都是静态页面。现在使用http模块与后端通信,变可以让我们的应用活起来。 
    我把后台服务写成了可跨域请求的webapi,这样在node上面调试起来就方便多了。

    创建服务模块

    ng g service account
    • 1

    ng给我们创建的模块account.service.ts,内容如下。 
    有关@Injectable和@Component,都是angular中的关键字或者关键注解。通过注解来表明js文件的类型,以方便angular框架进行调用。 
    @Component表示该js文件所导出的类是组件。 
    @Injectable表示该js文件所导出的文件是服务,而服务是可以通过注入来创建的。 
    服务的注入,是angular中用来剥离controller和业务逻辑的方式。

    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class AccountService {
    
      constructor() { }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    添加一个方法

      getBillTypes() {
        console.log('这是service里的方法');
      }
    • 1
    • 2
    • 3

    引用服务

    在accounting.component.ts里引用

    import {AccountService} from '../account.service';
    • 1
    @NgModule({
      providers: [
        AccountService
      ],
    })
    • 1
    • 2
    • 3
    • 4
    • 5

    推荐使用依赖注入的方式

      constructor(private service: AccountService) {
          service.getBillTypes(); // 调用方法
      }
    • 1
    • 2
    • 3

    查看下效果,提示错误。

    Unhandled Promise rejection: No provider for AccountService! ; Zone: angular ; Task: Promise.then ; Value:
    • 1

    原来是在app.module.ts 里面也要添加引用

    import {AccountService} from './account.service';
    • 1
      providers: [AccountService],
    • 1

    这下就完成了简单了例子。ng的编程风格越来越像我们使用的c#,java等的编程风格。当然编程思想也是越来越和我们后台开发相似了。 
    这里写图片描述

    整理下我们的后台接口

    添加一个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', // 获取统计信息
      GetTotallCount: host +  '/api/bill/GetTotallCount', // 获取求和数据
      AddBills: host +  '/api/bill/AddBills', // 添加记账信息
      DeleteBill: host +  '/api/bill/DeleteBill', // 删除记账信息
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在我们的service中引入

    import {Urls} from './Model/model.url';
    • 1

    整理方法

    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);
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    使用http模块

    在我们的app.module.ts中已经引入了

    import { HttpModule } from '@angular/http';
    • 1

    我们要在account.service.ts中引入

    import { Http } from '@angular/http';
    import 'rxjs/add/operator/toPromise';
    • 1
    • 2

    构造函数中注入依赖

      constructor(private http: Http) { }
    • 1

    修改getBillTypes方法试试,看请求返回数据和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);
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    http.get(url)(或者post put delete),访问服务器以后会返回一个observation对象,事实上是observation<服务器返回值>。通过toPromise转换成promise对象以后,就可以正常的使用then方法去处理返回值了。 
    通过promise的then方法,可以获得到服务器的返回值。个返回值都是json字符串,而在angular还是先按字符串处理。调用字符串的.json()方法转化为json数组或者json对象,继续调用关键字as将json数组或者json对象转化类,转化的方式是属性对应。 
    这里写图片描述

    因此我们修改方法,在model文件夹下添加自定义的Result类型,

    // 接口返回数据格式
    export class Result {
      error: any; // 错误时返回的信息
      result: any; // 成功时返回的数据
      success: boolean; // 是否成功
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在account.service.ts中引入并修改方法

    import {Result} from './Model/model.result';
    • 1
      getBillTypes(): Promise<Result> { // 获取记账类型
        return this.http.get(this.urls.GetBillTypes)
          .toPromise()
          .then(response =>  response.json() as Result)
          .catch(this.handleError);
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在accounting.component.ts中修改调用的方法

      constructor(private service: AccountService) {
          service.getBillTypes().then(r => { console.log(r); });
      }
    • 1
    • 2
    • 3

    这正是我们后台返回的数据且是json格式的。 
    这里写图片描述 
    这里我们用到了自定义类型Result的作用呢,看控制台打印的数据,对数据没什么影响,但是对我写代码是有帮助的。看下面: 
    这里写图片描述 
    对,会提示,如果使用了类型里没有的字段,还会报错。这活生生把一个弱类型语言变成了强类型的。当然如果不喜欢,我们可以不用自定义类。把自定义的Result换成any即可。 
    这里写图片描述

    完善service

    添加三个自定义类型

    // 记账类型的数据结构
    export class BillType {
      name: string;
      fontStyle: string;
      id: number;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    // 记账的数据结构
    export class Bill {
      id: number;
      creationTime: string;
      money: number;
      name: string;
      fontStyle: string;
      BillTypeId: number;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    要细分就太多了,大致分成这几类吧,引入并完善我们的方法

    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请求进行封装
     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请求进行封装
      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);
      }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    最后完善修结果如下:

    这里写图片描述

  • 相关阅读:
    Note/Solution 转置原理 & 多点求值
    Note/Solution 「洛谷 P5158」「模板」多项式快速插值
    Solution 「CTS 2019」「洛谷 P5404」氪金手游
    Solution 「CEOI 2017」「洛谷 P4654」Mousetrap
    Solution Set Border Theory
    Solution Set Stirling 数相关杂题
    Solution 「CEOI 2006」「洛谷 P5974」ANTENNA
    Solution 「ZJOI 2013」「洛谷 P3337」防守战线
    Solution 「CF 923E」Perpetual Subtraction
    KVM虚拟化
  • 原文地址:https://www.cnblogs.com/branton-design/p/7885991.html
Copyright © 2011-2022 走看看