详解封装基础的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处理textarea中的字符成每一行实例
Sep 22 Javascript
JavaScript实现的一个倒计时的类
Mar 12 Javascript
使用AOP改善javascript代码
May 01 Javascript
js实现表单Radio切换效果的方法
Aug 17 Javascript
javascript中加var和不加var的区别 你真的懂吗
Jan 06 Javascript
原生js仿淘宝网商品放大镜效果
Feb 28 Javascript
JavaScript fetch接口案例解析
Aug 30 Javascript
JavaScript实现简单轮播图效果
Dec 01 Javascript
使用node搭建自动发图文微博机器人的方法
Mar 22 Javascript
jQuery实现简单聊天室
Feb 08 jQuery
vue实现购物车结算功能
Jun 18 Javascript
JS中锚点链接点击平滑滚动并自由调整到顶部位置
Feb 06 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_Flame(Version:Progress)的原代码
2006/10/09 PHP
php中file_get_contents与curl性能比较分析
2014/11/08 PHP
实现WordPress主题侧边栏切换功能的PHP脚本详解
2015/12/14 PHP
PHP实现数组和对象的相互转换操作示例
2019/03/20 PHP
翻译整理的jQuery使用查询手册
2007/03/07 Javascript
JavaScript中的alert()函数使用技巧详解
2014/12/29 Javascript
javascript实现将文件保存到本地方法汇总
2015/07/26 Javascript
jQuery ajaxSubmit 实现ajax提交表单局部刷新
2016/07/04 Javascript
js实现统计字符串中特定字符出现个数的方法
2016/08/02 Javascript
微信小程序 自动登陆PHP源码实例(源码下载)
2017/05/08 Javascript
JavaScript实现微信号随机切换代码
2018/03/09 Javascript
vue使用自定义icon图标的方法
2018/05/14 Javascript
jQuery获取随机颜色的实例代码
2018/05/21 jQuery
js 数组详细操作方法及解析合集
2018/06/01 Javascript
vue实现多个元素或多个组件之间动画效果
2018/09/25 Javascript
使用weixin-java-miniapp配置进行单个小程序的配置详解
2019/03/29 Javascript
vue+echarts实现可拖动节点的折线图(支持拖动方向和上下限的设置)
2019/04/12 Javascript
JS函数基本定义与用法示例
2020/01/15 Javascript
Vue引入Stylus知识点总结
2020/01/16 Javascript
基于vue实现简易打地鼠游戏
2020/08/21 Javascript
[55:04]海涛DOTA2死魂复燃6.82版本介绍
2014/09/28 DOTA
[01:02:32]DOTA2-DPC中国联赛 正赛 iG vs PSG.LGD BO3 第二场 2月26日
2021/03/11 DOTA
python实现RSA加密(解密)算法
2016/02/17 Python
python 调用HBase的简单实例
2016/12/18 Python
如何高效使用Python字典的方法详解
2017/08/31 Python
Python爬虫框架scrapy实现的文件下载功能示例
2018/08/04 Python
python获取时间及时间格式转换问题实例代码详解
2018/12/06 Python
PyQT实现菜单中的复制,全选和清空的功能的方法
2019/06/17 Python
django如何实现视图重定向
2019/07/24 Python
pytorch::Dataloader中的迭代器和生成器应用详解
2020/01/03 Python
python开发实例之Python的Twisted框架中Deferred对象的详细用法与实例
2020/03/19 Python
美国中小型企业领先的办公家具供应商:Office Designs
2016/11/26 全球购物
大学毕业感言50字
2014/02/07 职场文书
专科生就业求职信
2014/06/22 职场文书
后勤工作个人总结
2015/02/28 职场文书
一起来学习Python的元组和列表
2022/03/13 Python