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

为什么要封装呢?

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:   Observable.throw    Observable<string>  string:处理后显示的错误文字
   **/
    public httpErrorFun(err:any):Observable<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);
    }
}

完整的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:   Observable.throw    Observable<string>  string:处理后显示的错误文字
   **/
    public httpErrorFun(err:any):Observable<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();
    }
}

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

据量子力学得到,点赞这篇文章的人都会成为欧皇,从此过着开心幸福的生活☺️。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,563评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,263评论 25 707
  • 推开浮游在记忆中金色教室的门,阳光洒在卷尺和铅笔的桌上,周围空无一人。揉捏散落在桌上的碎纸片,一本本整齐排列的书本...
    梅林爱橙子阅读 144评论 0 0
  • 昨天是儿童节,刷刷朋友圈,真是厉害,大家居然把每个大大小小的节日都过成了情人节,撒了一堆狗粮。 儿童节,最近这几年...
    洪木木阅读 277评论 0 0
  • 毫无征兆的离开 没了晚安 今晚该如何想念
    佛笑来人阅读 419评论 8 12