详解封装基础的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 相关文章推荐
js获取当月最后一天实例代码
Nov 19 Javascript
JavaScript验证电子邮箱的函数
Aug 22 Javascript
JS 新增Cookie 取cookie值 删除cookie 举例详解
Oct 10 Javascript
纯javascript实现简单下拉刷新功能
Mar 13 Javascript
jquery实现横向图片轮播特效代码分享
Nov 19 Javascript
原生js三级联动的简单实现代码
Jun 07 Javascript
JavaScript实现图片本地预览功能【不用上传至服务器】
Sep 20 Javascript
详解React Native 采用Fetch方式发送跨域POST请求
Nov 15 Javascript
JS 实现百度搜索功能
Feb 01 Javascript
JS中offset和匀速动画详解
Feb 06 Javascript
Layui实现数据表格默认全部显示(不要分页)
Oct 26 Javascript
简单了解Vue + ElementUI后台管理模板
Apr 07 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
PHP4之真OO
2006/10/09 PHP
PHP 操作文件的一些FAQ总结
2009/02/12 PHP
php连接Access数据库错误及解决方法
2013/06/20 PHP
ThinkPHP3.1新特性之命名范围的使用
2014/06/19 PHP
Symfony页面的基本创建实例详解
2015/01/26 PHP
功能强大的php文件上传类
2016/08/29 PHP
浅析php中array_map和array_walk的使用对比
2016/11/20 PHP
JS option location 页面跳转实现代码
2008/12/27 Javascript
JavaScript类和继承 prototype属性
2010/09/03 Javascript
原生js操作checkbox用document.getElementById实现
2013/10/12 Javascript
jquery的map与get方法详解
2013/11/04 Javascript
IE 下Enter提交表单存在重复提交问题的解决方法
2014/05/04 Javascript
javascript设置连续两次点击按钮时间间隔的方法
2014/10/28 Javascript
JS+CSS简单树形菜单实现方法
2015/09/12 Javascript
JS闭包与延迟求值用法示例
2016/12/22 Javascript
微信小程序实现图片轮播及文件上传
2017/04/07 Javascript
使用 jQuery 实现表单验证功能
2017/07/05 jQuery
vue-router相关基础知识及工作原理
2018/03/16 Javascript
快速解决bootstrap下拉菜单无法隐藏的问题
2018/08/10 Javascript
[01:38]完美世界DOTA2联赛(PWL)宣传片:第一站
2020/10/26 DOTA
深入理解python中函数传递参数是值传递还是引用传递
2017/11/07 Python
解读python如何实现决策树算法
2018/10/11 Python
Python cv2 图像自适应灰度直方图均衡化处理方法
2018/12/07 Python
python re库的正则表达式入门学习教程
2019/03/08 Python
python 普通克里金(Kriging)法的实现
2019/12/19 Python
Python更换pip源方法过程解析
2020/05/19 Python
css3背景_动力节点Java学院整理
2017/07/11 HTML / CSS
英国计算机商店:Technextday
2019/12/28 全球购物
澳大利亚家具商店:Freedom
2020/12/17 全球购物
RIP版本1跟版本2的区别
2013/12/30 面试题
车间机修工岗位职责
2014/02/28 职场文书
工程类专业自荐信范文
2014/03/09 职场文书
2014中学教师节广播稿
2014/09/10 职场文书
匿名信格式范文
2015/05/27 职场文书
雨雪天气温馨提示
2015/07/15 职场文书
Python上下文管理器Content Manager
2021/06/26 Python