专栏首页挖坑填坑Angular4记账webApp练手项目之五(Angular4项目中创建service(服务)和使用http模块)

Angular4记账webApp练手项目之五(Angular4项目中创建service(服务)和使用http模块)

前台源码

后台源码 说明:后台代码是用asp.net编写的,和http://www.jianshu.com/p/e6ed43227840这篇文章很像。其中还包含了其他一些练手的东西。

前言

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

创建服务模块

ng g service account

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() { }

}

添加一个方法

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

引用服务

在accounting.component.ts里引用

import {AccountService} from '../account.service';
@NgModule({
  providers: [
    AccountService
  ],
})

推荐使用依赖注入的方式

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

查看下效果,提示错误。

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

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

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

这下就完成了简单了例子。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', // 删除记账信息
};

在我们的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中已经引入了

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

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

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

构造函数中注入依赖

  constructor(private http: Http) { }

修改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);
  }

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; // 是否成功
}

在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中修改调用的方法

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

这正是我们后台返回的数据且是json格式的。

这里写图片描述

这里我们用到了自定义类型Result的作用呢,看控制台打印的数据,对数据没什么影响,但是对我写代码是有帮助的。看下面:

这里写图片描述

对,会提示,如果使用了类型里没有的字段,还会报错。这活生生把一个弱类型语言变成了强类型的。当然如果不喜欢,我们可以不用自定义类。把自定义的Result换成any即可。

这里写图片描述

完善service

添加三个自定义类型

// 记账类型的数据结构
export class BillType {
  name: string;
  fontStyle: string;
  id: number;
}
// 记账的数据结构
export class Bill {
  id: number;
  creationTime: string;
  money: number;
  name: string;
  fontStyle: string;
  BillTypeId: number;
}

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

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);
  }
}

最后完善修结果如下:

这里写图片描述

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用.net core ABP和Angular模板构建博客管理系统(实现编辑页面功能)

    别忘记app.module.ts中也需要引入ReactiveFormsModule

    易兒善
  • angular使用NG ZORRO来构建博客展示项目(简单实现展示页面)

    这两个并没有设计成core模块的组件,但是也放在这里,不知道放在哪里合适。有的可以不用设计成angular模块或者组件,初学者真烦恼

    易兒善
  • Asp.net+Vue2构建简单记账WebApp之六(vue.js构建记账统计页面)

    易兒善
  • 在前端中理解MVC服务之TypeScript篇

    通过开发一个网页应用来理解构建前端应用的方法,其中,使用JavaScript作为脚本语言,并转向使用JavaScript/TypeScript作为面向对象程序开...

    学前端
  • 基于 Vue 的商品主图放大镜方案

    在做电商类应用时,难免会遇到商品主图实现放大镜效果的场景,现有的基于Vue的第三方包不多并且无法直接复用,今天,我来分享一种高稳定性的基于 Vue 的图片放大镜...

    政采云前端团队
  • Node.js 里,如何凭空创建一个以假乱真的 FileStream?

    感谢支持ayqy个人订阅号,每周义务推送1篇(only unique one)原创精品博文,话题包括但不限于前端、Node、Android、数学...

    ayqy贾杰
  • 聊聊spring cloud的FeignClientFactoryBean

    本文主要研究一下spring cloud的FeignClientFactoryBean

    codecraft
  • 聊聊spring cloud的FeignClientFactoryBean

    本文主要研究一下spring cloud的FeignClientFactoryBean

    codecraft
  • Dev 等待提示 WaitDialogForm 另外版

       一、Dev的等待提示框                                                                  ...

    跟着阿笨一起玩NET
  • 9. SOFAJRaft源码分析— Follower如何通过Snapshot快速追上Leader日志?

    如果用户需开启 SOFAJRaft 的 Snapshot 机制,则需要在其客户端中设置配置参数类 NodeOptions 的“snapshotUri”属性(即为...

    luozhiyun

扫码关注云+社区

领取腾讯云代金券