资讯专栏INFORMATION COLUMN

Angular2中拦截器Intercept探索之路

instein / 2192人阅读

摘要:初衷之前看到正式发布了,过去看了下,感觉不错,于是入坑。不过思路还是可以借鉴的。尝试以下第一篇链接第二篇链接第三篇里写法过时了按照上述代码,写法与不同,不知道怎么改。

初衷

之前看到angular2正式发布了,过去看了下,感觉不错,于是入坑。
使用过程中想写一个像angular1那样的拦截器,一路坎坷啊

Angular1中的拦截器
.factory("HttpRequestInterceptor", ["$q", "$injector", "ConfigService", "DialogService", function($q, $injector, ConfigService, DialogService) {
    return {
        request: function(config) {
            if (config.method === "POST") {
                config.timeout = 60000;
                if (config.data === undefined) {
                    config.data = {
                        nologin: 999
                    };
                } else {
                    config.data.nologin = 999;
                }
            }
            return config;
        },
        requestError: function(rejection) {
            DialogService.alert("发送请求失败,请检查网络");
            return $q.reject(rejection);
        },
        response: function(resp) {
            if (resp.data.code !== undefined && resp.data.code !== 0) {
                if (resp.data.code === 5003) {
                    var stateService = $injector.get("$state");
                    stateService.go("login", {}, {
                        reload: true
                    });
                } else {
                    DialogService.alert(resp.data.msg);
                }
            }
            return resp;
        },
        responseError: function(rejection) {
            console.log(rejection);
            if (rejection.status === 0) {
                DialogService.alert("请求响应错误,请检查网络");
            } else if (rejection.status === 500) {
                DialogService.alert("服务器出错");
            } else {
                DialogService.alert("请求失败,请检查网络");
            }
            return $q.reject(rejection);
        }
    };
}])
Angular2中没有提供,需要自己实现

去Stackoverflow上搜了好久,有相关内容是不错,但过时了。不过思路还是可以借鉴的。

尝试以下
第一篇链接
第二篇链接
第三篇

@Injectable()
export class CustomHttp extends Http {
  constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) {
    super(backend, defaultOptions);
  }

  request(url: string | Request, options?: RequestOptionsArgs): Observable {
    console.log("request...");
    return super.request(url, options).catch(res => {
      // do something
    });        
  }

  get(url: string, options?: RequestOptionsArgs): Observable {
    console.log("get...");
    return super.get(url, options).catch(res => {
      // do something
    });
  }
}

app.module.ts里写法过时了

bootstrap(AppComponent, [HTTP_PROVIDERS,
    new Provider(Http, {
      useFactory: (backend: XHRBackend, defaultOptions: RequestOptions) => new CustomHttp(backend, defaultOptions),
      deps: [XHRBackend, RequestOptions]
  })
]);

按照上述代码,写法与angular2 r6不同,不知道怎么改。继续搜索,发现大部分写法都雷同,只是注入方式不同,后面看到了r6的注入方式,折腾几次,有了结果

自己的Intercept

customhttp.ts

import { Injectable } from "@angular/core";
import { Http, Request, RequestOptionsArgs, Response, RequestOptions, ConnectionBackend, Headers } from "@angular/http";
import "rxjs/Rx";
import { Observable } from "rxjs/Observable";
import { PubSubService } from "./shared/pubsub.service";
@Injectable()
export class CustomHttp extends Http {
    _pubsub: PubSubService;
    constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, pubsub: PubSubService) {
        super(backend, defaultOptions);
        this._pubsub = pubsub;
    }
    request(url: string | Request, options ? : RequestOptionsArgs): Observable < Response > {
        console.log("good");
        return this.intercept(super.request(url, options));
    }
    get(url: string, options ? : RequestOptionsArgs): Observable < Response > {
        return this.intercept(super.get(url, options));
    }
    post(url: string, body: string, options ? : RequestOptionsArgs): Observable < Response > {
        return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
    }
    put(url: string, body: string, options ? : RequestOptionsArgs): Observable < Response > {
        return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
    }
    delete(url: string, options ? : RequestOptionsArgs): Observable < Response > {
        return this.intercept(super.put(url, this.getRequestOptionArgs(options)));
    }
    getRequestOptionArgs(options ? : RequestOptionsArgs): RequestOptionsArgs {
        if (options == null) {
            options = new RequestOptions();
        }
        if (options.headers == null) {
            options.headers = new Headers();
        }
        options.headers.append("Content-Type", "application/json");
        return options;
    }
    intercept(observable: Observable < Response > ): Observable < Response > {
        this._pubsub.beforeRequest.emit("beforeRequestEvent")
        observable.subscribe(null, (err) => {
            console.log("err");
            this._pubsub.afterRequest.emit("afterRequestEvent");
            this.handleError(err.status);
        }, () => {
            console.log("complete");
            this._pubsub.afterRequest.emit("afterRequestEvent");
        });
        return observable;
    }
    handleError(status) {
        if (status === 0) {
            this._pubsub.errorToast.emit("请求响应错误,请检查网络");
        } else if (status === 404) {
            this._pubsub.errorToast.emit("请求链接不存在,请联系管理员");
        } else if (status === 500) {
            this._pubsub.errorToast.emit("服务器出错,请稍后再试");
        } else {
            this._pubsub.errorToast.emit("未知错误,请检查网络");
        }
    }
}

pubsup.service.ts

import { Injectable } from "@angular/core";
import { Subject } from "rxjs/Subject";
// 发布订阅事件, 继承自Subject, emit用于发射事件
class PubSubEvent extends Subject < String > {
    constructor() {
        super();
    }
    emit(value) { super.next(value); }
}
@Injectable()
export class PubSubService {
    beforeRequest: PubSubEvent;
    afterRequest: PubSubEvent;
    errorToast: PubSubEvent;
    successToast: PubSubEvent;
    showPupup: PubSubEvent;
    hidePupup: PubSubEvent;
    confirm: PubSubEvent;
    constructor() {
        this.beforeRequest = new PubSubEvent();
        this.afterRequest = new PubSubEvent();
        this.errorToast = new PubSubEvent();
        this.successToast = new PubSubEvent();
        this.showPupup = new PubSubEvent();
        this.hidePupup = new PubSubEvent();
        this.confirm = new PubSubEvent();
    }
}

app.module.ts

import { NgModule, Injectable } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { HttpModule, Http, XHRBackend, RequestOptions } from "@angular/http";
// import { InMemoryWebApiModule } from "angular-in-memory-web-api";
import { HeroData } from "./hero/hero-data";
import { routing } from "./app.routing";
import { AppComponent } from "./app.component";
import { CrisisCenterComponent } from "./crisis/crisis-center.component";
import { MapComponent } from "./map/map.component";
import { CustomHttp } from "./customhttp";
import { MapService } from "./map/map.service";

import { PubSubService } from "./shared/pubsub.service";

import { PubSubComponent } from "./shared/pubsub.component";
@NgModule({
    declarations: [
        AppComponent, CrisisCenterComponent, MapComponent, PubSubComponent
    ],
    imports: [
        BrowserModule,
        FormsModule,
        HttpModule,
        // InMemoryWebApiModule.forRoot(HeroData),
        routing
    ],
    providers: [
        MapService,
        PubSubService, {
            provide: Http,
            useFactory: (backend: XHRBackend, 
                defaultOptions: RequestOptions, 
                pubsub: PubSubService) => new CustomHttp(backend, defaultOptions, pubsub),
            deps: [XHRBackend, RequestOptions, PubSubService]
        }
    ],
    bootstrap: [AppComponent],
})
export class AppModule {}

最后是pubsup.component.ts,我是将loading, toast, pupup放在了一起
loading将在每个请求前显示,请求失败或结束隐藏
toast将在请求失败显示2秒钟,或者在其他组件里调用
pupup将在删除事件前提问,想放在delete api里自动显示并处理,但是没有实现
具体代码在我github:https://github.com/jiangbo201...

import { Component, Input } from "@angular/core";
import { Http } from "@angular/http";
import { PubSubService } from "./pubsub.service";
@Component({
    selector: "app-pubsub",
    templateUrl: "./pubsub.component.html",
    styleUrls: ["./pubsub.component.css"]
})
export class PubSubComponent {
    showloading = false;
    showPupub = false;
    showSuccessToast = false;
    showErrorToast = false;
    errorValue: any = "error";
    successValue: any = "success";
    _pubsub: PubSubService;
    constructor(public http: Http, public pubsub: PubSubService) {
        this._pubsub = pubsub;
    }
    cancel() {
            this.showPupub = false;
    }
    confirm() {
            this.showPupub = false;
            this._pubsub.confirm.emit("confirm");
    }
    ngOnInit() {
        
        this._pubsub.beforeRequest.subscribe(data => {
            console.log(data);
            this.showloading = true;
        });
        this._pubsub.afterRequest.subscribe(data => {
            console.log(data);
            this.showloading = false;
        });
        this._pubsub.errorToast.subscribe(data => {
            console.log(data);
            this.showErrorToast = true;
            this.errorValue = data;
            let that = this;
            // setTimeout(function() {
            //     console.log(this);
            //     that.showErrorToast = false;
            // }, 2000);
        });
        this._pubsub.successToast.subscribe(data => {
            console.log(data);
            this.showSuccessToast = true;
            this.successValue = data;
            let that = this;
            setTimeout(function() {
                that.showSuccessToast = false;
            }, 2000);

        });
        this._pubsub.showPupup.subscribe(data => {
            this.showPupub = true;
            console.log(data);
        });
        this._pubsub.hidePupup.subscribe(data => {
            console.log(data);
            this.showPupub = false;
        });
    }
}

最后,我想在每个删除aip里自动拦截,并弹出提示,如果确定删除就执行,如果放弃就return
但是不知道怎么阻塞执行,欢迎交流

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80661.html

相关文章

  • GMTC 2019 参会回顾

    摘要:回顾上一次参加还是年。年的还是真正的,年的会议早已经把英文全称去掉,改称全球大前端技术大会。同时与产品协作从产品设计方面突出关注点,做产品设计方面的优化,如站新版改造减少页面元素,将播放器窗口直接显示在第一屏。 回顾 上一次参加 GMTC 还是 2017 年。那时的我还是刚刚参加工作并在试用期辞职的菜鸟。 2017 年的 GMTC 还是真正的 Global Mobile Tech Co...

    Zack 评论0 收藏0
  • 2017年2月份前端资源分享

    平日学习接触过的网站积累,以每月的形式发布。2017年以前看这个网址:http://www.kancloud.cn/jsfron... 1. Javascript 前端生成好看的二维码 十大经典排序算法(带动图演示) 为什么知乎前端圈普遍认为H5游戏和H5展示的JSer 个人整理和封装的YU.js库|中文详细注释|供新手学习使用 扩展JavaScript语法记录 - 掉坑初期工具 汉字拼音转换...

    lily_wang 评论0 收藏0
  • 2017年2月份前端资源分享

    平日学习接触过的网站积累,以每月的形式发布。2017年以前看这个网址:http://www.kancloud.cn/jsfron... 1. Javascript 前端生成好看的二维码 十大经典排序算法(带动图演示) 为什么知乎前端圈普遍认为H5游戏和H5展示的JSer 个人整理和封装的YU.js库|中文详细注释|供新手学习使用 扩展JavaScript语法记录 - 掉坑初期工具 汉字拼音转换...

    chengjianhua 评论0 收藏0
  • 2017年2月份前端资源分享

    平日学习接触过的网站积累,以每月的形式发布。2017年以前看这个网址:http://www.kancloud.cn/jsfron... 1. Javascript 前端生成好看的二维码 十大经典排序算法(带动图演示) 为什么知乎前端圈普遍认为H5游戏和H5展示的JSer 个人整理和封装的YU.js库|中文详细注释|供新手学习使用 扩展JavaScript语法记录 - 掉坑初期工具 汉字拼音转换...

    Anonymous1 评论0 收藏0
  • 2017年2月份前端资源分享

    平日学习接触过的网站积累,以每月的形式发布。2017年以前看这个网址:http://www.kancloud.cn/jsfron... 1. Javascript 前端生成好看的二维码 十大经典排序算法(带动图演示) 为什么知乎前端圈普遍认为H5游戏和H5展示的JSer 个人整理和封装的YU.js库|中文详细注释|供新手学习使用 扩展JavaScript语法记录 - 掉坑初期工具 汉字拼音转换...

    dreamtecher 评论0 收藏0

发表评论

0条评论

instein

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<