详解封装基础的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和DOM Interfaces来处理HTML
Oct 09 Javascript
js中通过split函数分割字符串成数组小例子
Sep 21 Javascript
javascript:window.open弹出窗口的位置问题
Mar 18 Javascript
从零学JSON之JSON数据结构
May 19 Javascript
原生javascript获取元素样式
Dec 31 Javascript
浅析C/C++,Java,PHP,JavaScript,Json数组、对象赋值时最后一个元素后面是否可以带逗号
Mar 22 Javascript
第九章之路径分页标签与徽章组件
Apr 25 Javascript
基于gulp合并压缩Seajs模块的方式说明
Jun 14 Javascript
JS中位置与大小的获取方法
Nov 22 Javascript
详解用原生JavaScript实现jQuery的某些简单功能
Dec 19 Javascript
对vux点击事件的优化详解
Aug 28 Javascript
Vue中component标签解决项目组件化操作
Sep 04 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下关于中英数字混排的字符串分割问题
2010/04/06 PHP
php array_intersect比array_diff快(附详细的使用说明)
2011/07/03 PHP
php中实现简单的ACL 完结篇
2011/09/07 PHP
php中用date函数获取当前时间有误的解决办法
2013/08/02 PHP
PHPThumb图片处理实例
2014/05/03 PHP
PHP微信开发之有道翻译
2016/06/23 PHP
PHP中new static()与new self()的比较
2016/08/19 PHP
PHP实现微信图片上传到服务器的方法示例
2017/06/29 PHP
静态图片的十一种滤镜效果--不支持Ie7及非IE浏览器。
2007/03/06 Javascript
手把手教你自己写一个js表单验证框架的方法
2010/09/14 Javascript
简单实用jquery版三级联动select示例
2013/07/04 Javascript
javascript获取url上某个参数的方法
2013/11/08 Javascript
把文本中的URL地址转换为可点击链接的JavaScript、PHP自定义函数
2014/07/29 Javascript
js使用html()或text()方法获取设置p标签的显示的值
2014/08/01 Javascript
JavaScript中获取高度和宽度函数总结
2014/10/08 Javascript
js实现点击左右按钮轮播图片效果实例
2015/01/29 Javascript
javascript中的五种基本数据类型
2015/08/26 Javascript
jQuery插件formValidator实现表单验证
2016/05/23 Javascript
老生常谈js数据类型
2017/08/03 Javascript
微信小程序页面渲染实现方法
2019/11/06 Javascript
Django集成百度富文本编辑器uEditor攻略
2014/07/04 Python
Python理解递归的方法总结
2019/01/28 Python
Python爬虫爬取Bilibili弹幕过程解析
2019/10/10 Python
全球知名鞋履品牌授权零售商:Journeys
2016/09/17 全球购物
Ego Shoes官网:英国时髦鞋类品牌
2020/10/19 全球购物
是否可以从一个static方法内部发出对非static方法的调用?
2014/08/18 面试题
环境工程与管理大学毕业生求职信
2013/10/02 职场文书
大学生就业自荐信
2013/10/26 职场文书
工程业务员岗位职责
2013/12/31 职场文书
面试后的感谢信范文
2014/02/01 职场文书
文艺晚会主持词
2014/03/24 职场文书
乡镇安全生产目标责任书
2014/07/23 职场文书
入党转正申请报告
2015/05/15 职场文书
可怜妈妈观后感
2015/06/09 职场文书
仰望星空观后感
2015/06/10 职场文书
深入理解以DEBUG方式线程的底层运行原理
2021/06/21 Java/Android