Angular2中拦截器Intercept探索之路

初衷

之前看到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<Response> {
    console.log('request...');
    return super.request(url,options).catch(res => {
      // do something
    });        
  }

  get(url: string,options?: RequestOptionsArgs): Observable<Response> {
    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,options ? : RequestOptionsArgs): Observable < Response > {
        return this.intercept(super.put(url,this.getRequestOptionArgs(options)));
    }
    delete(url: string,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,pubsub: PubSubService) => new CustomHttp(backend,defaultOptions,pubsub),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但是不知道怎么阻塞执行,欢迎交流

相关文章

ANGULAR.JS:NG-SELECTANDNG-OPTIONSPS:其实看英文文档比看中...
AngularJS中使用Chart.js制折线图与饼图实例  Chart.js 是...
IE浏览器兼容性后续前言 继续尝试解决IE浏览器兼容性问题,...
Angular实现下拉菜单多选写这篇文章时,引用文章地址如下:h...
在AngularJS应用中集成科大讯飞语音输入功能前言 根据项目...
Angular数据更新不及时问题探讨前言 在修复控制角标正确变...