详解封装基础的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 相关文章推荐
JavaScript面象对象设计
Apr 28 Javascript
Javascript 继承机制的实现
Aug 12 Javascript
[JSF]使用DataModel处理表行事件的实例代码
Aug 05 Javascript
一个实用的图片切换支持点击切换和自动轮播
Sep 09 Javascript
9款2014最热门jQuery实用特效推荐
Dec 07 Javascript
jquery获取当前元素索引值用法实例
Jun 10 Javascript
JS中的phototype详解
Feb 04 Javascript
node实现简单的反向代理服务器
Jul 26 Javascript
jQuery实现腾讯信用界面(自制刻度尺)样式
Aug 15 jQuery
JavaScript实现兼容IE6的收起折叠与展开效果实例
Sep 20 Javascript
微信小程序 swiper组件构建轮播图的实例
Sep 20 Javascript
vue下history模式刷新后404错误解决方法
Aug 18 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
phpMyAdmin 安装教程全攻略
2007/03/19 PHP
3种方法轻松处理php开发中emoji表情的问题
2016/07/18 PHP
php实现异步将远程链接上内容(图片或内容)写到本地的方法
2016/11/30 PHP
Firebug入门指南(Firefox浏览器)
2010/08/21 Javascript
模拟jQuery ajax服务器端与客户端通信的代码
2011/03/28 Javascript
javascript firefox 自动加载iframe 自动调整高宽示例
2013/08/27 Javascript
弹出最简单的模式化遮罩层的js代码
2013/12/04 Javascript
jquery得到iframe src属性值的方法
2014/09/25 Javascript
深入探密Javascript数组方法
2015/01/08 Javascript
js实现简单锁屏功能实例
2015/05/27 Javascript
iframe跨域通信封装详解
2015/08/11 Javascript
基于javascript实现泡泡大冒险网页版小游戏
2016/03/23 Javascript
基于javascript实现tab切换特效
2016/03/29 Javascript
AngularJS中实现用户访问的身份认证和表单验证功能
2016/04/21 Javascript
SWFUpload多文件上传及文件个数限制的方法
2016/05/31 Javascript
Angular2搜索和重置按钮过场动画
2017/05/24 Javascript
深入理解基于vue-cli的vuex配置
2017/07/24 Javascript
基于JavaScript实现带数据验证和复选框的表单提交
2017/08/23 Javascript
Vue打包后出现一些map文件的解决方法
2018/02/13 Javascript
在react-antd中弹出层form内容传递给父组件的操作
2020/10/24 Javascript
python通过cookie模拟已登录状态的初步研究
2016/11/09 Python
Python 正则表达式入门(初级篇)
2016/12/07 Python
Python3实现发送QQ邮件功能(附件)
2020/12/23 Python
用Python+OpenCV对比图像质量的几种方法
2019/07/15 Python
python__new__内置静态方法使用解析
2020/01/07 Python
python处理RSTP视频流过程解析
2020/01/11 Python
使用Python脚本从文件读取数据代码实例
2020/01/19 Python
基于HTML5代码实现折叠菜单附源码下载
2015/11/27 HTML / CSS
给男朋友的道歉信
2014/01/12 职场文书
村委会贫困证明
2014/01/14 职场文书
思想品德课教学反思
2014/02/10 职场文书
捐款感谢信
2015/01/20 职场文书
监考失职检讨书
2015/01/26 职场文书
春季运动会加油词
2015/07/18 职场文书
用Python提取PDF表格的方法
2021/04/11 Python
关于Nginx中虚拟主机的一些冷门知识小结
2022/03/03 Servers