详解封装基础的angular4的request请求方法


Posted in Javascript onJune 05, 2018

为什么要封装呢?

angular4自身提供的请求方法是用Observable来实现的。用的是观察者模式,个人认为这用来写请求是非常方便的。

一个项目里会有非常多的不同的请求,但是其实每个请求都会有些共性。比如:每个请求都要传Authorization,比如每个请求都要先判断后台返回的status字段为200时才是请求成功,后台正真返回的数据在data字段里,比如对于错误信息的处理都是一样的......等等。

所以我们需要封装出一个请求,去统一处理这些问题,从而保证组件里调用请求方法的时候收到的值都是可以直接拿来用的,几乎不用再写些重复的代码。

希望封装成什么样呢?

当然是越少重复的代码越好,我们就是想偷懒!!!!

怎么实现呢?

首先先新建一个请求的service,文件名为:request.service.ts。然后跟着我来虚拟需求,一步一步的慢慢来完善这个service。

需求A

1.请求方式为get。

2.默认的请求超时时间为3秒,可传入别的超时时间。

3.后台返回的成功的json为这样:

{
  "status": 200,
  "data"  : ...
}

错误时这样:

{
  "status": 201,
  "msg"  : "用户名或密码错误"
}

实现A

request.service.ts

/**
 ********************************************************************************************
 * @App: test
 * @author: isiico
 * @type: service
 * @src: services/request.service.ts
 *
 * @descriptions:
 * 请求的服务
 *
 ********************************************************************************************
 */
// Angular Core
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';

// rxjs
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/timeout';
import 'rxjs/add/observable/throw';

@Injectable()
export class RequestService {
  private setTimeout = 3000; // 默认的超时时间

  constructor(private http:HttpClient) {
  }
  
   /** 获取数据
    * param: url  string   必填,请求的url
    *     time  number   可不填,请求的超时时间,如不填,默认为setTimeout
    * return:    Observable HttpClient的get请求,请求完成后返回的值类型是any
    **/
   public getData(url, time = this.setTimeout):Observable<any> {
    let thiUrl = url; // 用到的url
    let thisTime = time; // 用到的超时时间
    return this.http.get(thiUrl)
       .timeout(thisTime)
       .map(res => this.resFun(res));
   }

   /** 返回数据的处理
    * param:  data   any   必填,需要处理的数据
    * return:  res   any   返回处理后的值
    **/
   private resFun(data:any):any {
    let thisData:any = data; // 需要处理的值
    let res:any; // 最终值

    // 当status为200时
    if (thisData['status'] == 200) {
       res = thisData['data']; // 给最终值赋值
    } else {
    // 当status不为200时
      let err = thisData['msg']; // 错误信息
      throw new Error(err); // 抛出错误
    }
    return res; // 返回最终值
   }
}

需求B

1.为了安全,后台要求请求的头需要加上Authorization参数。

2.当请求失败(如404,500这种)时,处理好错误信息,最后的错误信息要像 实现A 里一样,是可以直接用的字符串类型的错误信息。

实现B

request.service.ts (只展示新增的代码,完整代码后面有)

import 'rxjs/add/operator/catch';

@Injectable()
export class RequestService {

   /** 添加Authorization的属性 */
   private addAuthorization(options:any):void { 
    options['headers'] = { 
       'Authorization': '1drf5dg4d7s4w7z', 
    }; 
   } 
  
   /** 获取数据
    * param: url  string   必填,请求的url
    *     time  number   可不填,请求的超时时间,如不填,默认为setTimeout
    * return:    Observable HttpClient的get请求,请求完成后返回的值类型是any
    **/
   public getData(url, time = this.setTimeout):Observable<any> {
    let thiUrl = url; // 用到的url
    let options = {}; // 请求的设置
    let thisTime = time; // 用到的超时时间
    this.addAuthorization(options); // 请求头里添加Authorization参数
    return this.http.get(thiUrl, options)
       .timeout(thisTime)
       .catch(this.httpErrorFun) // 处理错误信息(必须放在timeout和map之间)
       .map(res => this.resFun(res));
   }

  /** 对请求错误信息的处理
    * param:  err  any  必填,需要处理的错误信息
    * return:  res  string 处理后的结果
    **/
   public httpErrorFun(err:any):string { /* new */
    let res:string = ''; // 处理后的结果 /* new */
    let data:any = err; // 需要处理的值 /* new */

    /** 后台有返回错误信息时 */
    if (data.hasOwnProperty('error') && data.hasOwnProperty('message')) { /* new */
       res = data.message; /* new */

     /** 后台没有返回错误信息只有错误名时 */
    } else if (data.hasOwnProperty('name')) { /* new */
       let errName = data.name; /* new */

     /** 请求超时 */
     if (errName == 'TimeoutError') { /* new */
      res = '对不起,请求超时了'; /* new */
     }

     /** 后台返回未授权时 */
    } else if (data == "Unauthorization") { /* new */
       res = '您没有权限,请重新登录' /* new */
      } else {
       res = "哎呀,不知道是啥错误~~"; /* new */
    }

    return Observable.throw(res); /* new */
   }
}

完整的request service 代码

request.service.ts

/**
 ********************************************************************************************
 * @App: test
 * @author: isiico
 * @type: service
 * @src: services/request.service.ts
 *
 * @descriptions:
 * 请求的服务
 *
 ********************************************************************************************
 */
// Angular Core
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';

// rxjs
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/timeout';
import 'rxjs/add/observable/throw';
import 'rxjs/add/operator/catch';

@Injectable()
export class RequestService {
  private setTimeout:number = 3000; // 默认的超时时间

  constructor(private http:HttpClient) {
  }

   /** 添加Authorization的属性 */
   private addAuthorization(options:any):void {
    options['headers'] = {
       'Authorization': '1drf5dg4d7s4w7z',
    };
   }
  
   /** 获取数据
    * param: url  string   必填,请求的url
    *     time  number   可不填,请求的超时时间,如不填,默认为setTimeout
    * return:    Observable HttpClient的get请求,请求完成后返回的值类型是any
    **/
   public getData(url, time = this.setTimeout):Observable<any> {
    let thiUrl = url; // 用到的url
    let options = {}; // 请求的设置
    let thisTime = time; // 用到的超时时间
    this.addAuthorization(options); // 请求头里添加Authorization参数
    return this.http.get(thiUrl, options)
       .timeout(thisTime)
       .catch(this.httpErrorFun) // 处理错误信息(必须放在timeout和map之间)
       .map(res => this.resFun(res));
   }

   /** 返回数据的处理
    * param:  data   any   必填,需要处理的数据
    * return:  res   any   返回处理后的值
    **/
   private resFun(data:any):any {
    let thisData:any = data; // 需要处理的值
    let res:any; // 最终值

    // 当status为200时
    if (thisData['status'] == 200) {
       res = thisData['data']; // 给最终值赋值
    } else {
    // 当status不为200时
      let err = thisData['msg']; // 错误信息
      throw new Error(err); // 抛出错误
    }
    return res; // 返回最终值
   }

  /** 对请求错误信息的处理
    * param:  err  any  必填,需要处理的错误信息
    * return:  res  string 处理后的结果
    **/
   public httpErrorFun(err:any):string {
    let res:string = ''; // 处理后的结果
    let data:any = err; // 需要处理的值

    /** 后台有返回错误信息时 */
    if (data.hasOwnProperty('error') && data.hasOwnProperty('message')) {
       res = data.message;

     /** 后台没有返回错误信息只有错误名时 */
    } else if (data.hasOwnProperty('name')) {
       let errName = data.name;

     /** 请求超时 */
     if (errName == 'TimeoutError') {
      res = '对不起,请求超时了';
     }

     /** 后台返回未授权时 */
    } else if (data == "Unauthorization") {
       res = '您没有权限,请重新登录';
      } else {
       res = "哎呀,不知道是啥错误~~";
    }

    return Observable.throw(res);
   }
}

小结

至此,我们已经完成了一个满足基本需求的,可以公共使用的请求服务,接下来我们来看怎么在组件内调用。

调用

我们有个叫list的组件,要调用get请求,请求成功显示数据,请求失败,显示错误信息。

list.component.ts

/**
 ********************************************************************************************
 * @App: test
 * @author: isiico
 * @type: component
 * @src: components/list.component.ts
 *
 * @descriptions:
 * list组件
 *
 ********************************************************************************************
 */
// Angular Core
import { Component, OnInit } from '@angular/core';

// Services
import { RequestService } from "../services/request.service";

@Component({
 moduleId: module.id,
 templateUrl: 'list.component.html'
})

export class ListComponent implements OnInit {
  listApi = '/assets/mock-data/list.json'; // 列表的api地址
  list:Array<any>; // 列表数据(类型为数组)
  listErrMsg: string = ''; // 列表请求的错误信息
  
  constructor(private req: RequestService) {
  }
  
  /** 获取list */
  getList(){
    this.listErrMsg = ''; // 清空错误信息

    // 发送请求
    this.req.getData(this.cabinetListApi)
       .subscribe(
      res=>{
      // 请求成功
        this.cabinets = [];
        this.cabinets = res;
       },err=>{
      // 请求失败
        this.cabinets = [];
        this.listErrMsg = err;
     })

   }
  
  ngOnInit() {
    this.getList();
   }
}

页面的显示自己去完成吧!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery imgareaselect 使用利用js与程序结合实现图片剪切
Jul 30 Javascript
JS面向对象编程 for Cookie
Sep 19 Javascript
jquery 圆形旋转图片滚动切换效果
Jan 19 Javascript
javascript中的变量作用域以及变量提升详细介绍
Oct 24 Javascript
js判断当前浏览器类型,判断IE浏览器方法
Jun 02 Javascript
JSONP跨域GET请求解决Ajax跨域访问问题
Dec 31 Javascript
jQuery+css3实现Ajax点击后动态删除功能的方法
Aug 10 Javascript
js+html5操作sqlite数据库的方法
Feb 02 Javascript
浅谈JavaScript 浏览器对象
Jun 03 Javascript
微信小程序 textarea 组件详解及简单实例
Jan 10 Javascript
浅谈Vuex@2.3.0 中的 state 支持函数申明
Nov 22 Javascript
js中的数组对象排序分析
Dec 11 Javascript
React.js绑定this的5种方法(小结)
Jun 05 #Javascript
微信小程序实现城市列表选择
Jun 05 #Javascript
vue.js将时间戳转化为日期格式的实现代码
Jun 05 #Javascript
如何使node也支持从url加载一个module详解
Jun 05 #Javascript
Js中将Long转换成日期格式的实现方法
Jun 05 #Javascript
JS非行间样式获取函数的实例代码
Jun 05 #Javascript
JavaScript实现读取与输出XML文件数据的方法示例
Jun 05 #Javascript
You might like
php笔记之:php函数range() round()和list()的使用说明
2013/04/26 PHP
开源php中文分词系统SCWS安装和使用实例
2014/04/11 PHP
PHP实现合并discuz用户
2015/08/05 PHP
javascript 面向对象编程 function也是类
2009/09/17 Javascript
用js来解决ajax读取页面乱码
2010/11/28 Javascript
三级下拉菜单的js实现代码
2011/05/23 Javascript
在JS中解析HTML字符串示例代码
2014/04/16 Javascript
JQuery中使用.each()遍历元素学习笔记
2014/11/08 Javascript
jQuery实现美观的多级动画效果菜单代码
2015/09/06 Javascript
用JS生成UUID的方法实例
2016/03/30 Javascript
js中最容易被忽视的事件问题大总结
2016/05/15 Javascript
js和C# 时间日期格式转换的简单实例
2016/05/28 Javascript
JavaScript如何实现跨域请求
2016/08/05 Javascript
TypeScript入门-接口
2017/03/30 Javascript
详解webpack 多页面/入口支持&amp;公共组件单独打包
2017/06/29 Javascript
解决vue里碰到 $refs 的问题的方法
2017/07/13 Javascript
Vue 将后台传过来的带html字段的字符串转换为 HTML
2018/03/29 Javascript
浅谈React的最大亮点之虚拟DOM
2018/05/29 Javascript
浅析Vue项目中使用keep-Alive步骤
2018/07/27 Javascript
vue实现下载文件流完整前后端代码
2020/11/17 Vue.js
Python 遍历子文件和所有子文件夹的代码实例
2016/12/21 Python
Python实现破解12306图片验证码的方法分析
2017/12/29 Python
Python cookbook(数据结构与算法)从字典中提取子集的方法示例
2018/03/22 Python
python 显示数组全部元素的方法
2018/04/19 Python
Python实现修改IE注册表功能示例
2018/05/10 Python
python环境路径配置以及命令行运行脚本
2019/04/02 Python
Python 获取指定文件夹下的目录和文件的实现
2019/08/30 Python
Python AutoCAD 系统设置的实现方法
2020/04/01 Python
Python中实现输入一个整数的案例
2020/05/03 Python
python制作微博图片爬取工具
2021/01/16 Python
一款恶搞头像特效的制作过程 利用css3和jquery
2014/11/21 HTML / CSS
函授毕业个人自我评价
2014/02/20 职场文书
商场促销活动总结
2014/07/10 职场文书
入党积极分子半年考察意见
2015/06/02 职场文书
2015暑假假期总结
2015/07/13 职场文书
浅析Django接口版本控制
2021/06/26 Python