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

    最后完善修结果如下:

    这里写图片描述

  • 相关阅读:
    搭建consul cluster(三节点)
    php设计模式之:装饰者模式
    php设计模式之:中介者模式
    PECL 和 PEAR
    firefox汉化(利用中文插件)
    数据结构之最小树生成(用php描述)
    php设计模式之:观察者模式
    Ubuntu安装Microsoft Windows Fonts微软字体库
    mysql事物处理
    php数字转中文
  • 原文地址:https://www.cnblogs.com/branton-design/p/7885991.html
Copyright © 2011-2022 走看看