我试图在AngularJS中制作拦截器.我对AngularJS很新,发现了一些Interceptor的例子,但是无法让它工作.
在这里,我有我的app.js文件,其中包含所有相关代码.我还有一个控制器调用REST api并返回JSONP.
首先,我声明模块然后配置它(定义Interceptor).它现在应该捕获所有请求并输出到控制台...
使用app.factory创建拦截器是错误的吗?
var app = angular.module(
'TVPremieresApp',
[
'app.services'
, 'app.controllers'
]
);
app.config(function ($httpProvider) {
$httpProvider.responseInterceptors.push('errorInterceptor');
});
app.service('MessageService', function () {
// angular strap alert directive supports multiple alerts.
// Usually this is a distraction to user.
//Let us limit the messages to one
this.messages = [];
this.setError = function(msg) {
this.setMessage(msg, 'error', 'Error:');
};
this.setSuccess = function(msg) {
this.setMessage(msg, 'success', 'Success:');
};
this.setInfo = function (msg) {
this.setMessage(msg, 'info', 'Info:');
};
this.setMessage = function(content, type, …Run Code Online (Sandbox Code Playgroud) 在延迟加载的功能模块和功能子模块中使用核心模块服务的最佳做法是什么.
根据Angular样式指南,我有以下内容
app
-core
- core.module.ts
-logger.service.ts
-token-interceptor.service.ts
-authentication.service.ts
-shared
-shared.module.ts
-base module (my feature base , lazy loaded with router-outlet)
-base.module.ts
-base.routing.module.ts
-base
-base.component.ts
-admin (lazy loaded , child module of base module)
-admin.module.ts
-admin.routing.ts
-admin-component.ts
-report(lazy loaded , child module of base module, sibling of admin)
-report.module.ts
-report.routing.ts
-report-component.ts
Run Code Online (Sandbox Code Playgroud)
如果我在所有功能模块中添加TokenInterceptorService作为提供程序,那么HTTP拦截器可以正常工作.当我在App模块中添加它时(但不是在延迟加载的功能模块中)它不会拦截延迟加载的功能模块中触发的http请求.
使用核心模块中声明的服务/拦截器的最佳实践是什么?
app.module.ts
@NgModule({
declarations: [
AppComponent,
LoginComponent,
],
imports: [
BrowserModule,BrowserAnimationsModule, CoreModule, AppRoutingModule, FormsModule
], providers: [{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptorService, multi: true }],
bootstrap: [AppComponent]
})
export …Run Code Online (Sandbox Code Playgroud) 我创建了一个角度拦截器来检查我的身份令牌的有效性.不知何故,do角度无法识别该方法.subscribe工作,但我不想要这个解决方案,因为它将我的请求加倍发送到服务器.
TypeError: next.handle(...).do is not a function
at AuthTokenService.webpackJsonp.../../../../../src/app/commons/services/interceptors/auth-token.service.ts.AuthTokenService.intercept (auth-token.service.ts:37)
at HttpInterceptorHandler.webpackJsonp.../../../common/esm5/http.js.HttpInterceptorHandler.handle (http.js:1796)
at XsrfService.webpackJsonp.../../../../../src/app/commons/services/interceptors/xsrf.service.ts.XsrfService.intercept (xsrf.service.ts:15)
at HttpInterceptorHandler.webpackJsonp.../../../common/esm5/http.js.HttpInterceptorHandler.handle (http.js:1796)
at HttpXsrfInterceptor.webpackJsonp.../../../common/esm5/http.js.HttpXsrfInterceptor.intercept (http.js:2489)
at HttpInterceptorHandler.webpackJsonp.../../../common/esm5/http.js.HttpInterceptorHandler.handle (http.js:1796)
at MergeMapSubscriber.project (http.js:1466)
at MergeMapSubscriber.webpackJsonp.../../../../rxjs/_esm5/operators/mergeMap.js.MergeMapSubscriber._tryNext (mergeMap.js:128)
at MergeMapSubscriber.webpackJsonp.../../../../rxjs/_esm5/operators/mergeMap.js.MergeMapSubscriber._next (mergeMap.js:118)
at MergeMapSubscriber.webpackJsonp.../../../../rxjs/_esm5/Subscriber.js.Subscriber.next (Subscriber.js:92)
Run Code Online (Sandbox Code Playgroud)
这是我的拦截器代码:
import { Injectable, NgModule} from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from
'@angular/common/http';
import { SessionService } from 'app/commons/services/auth/session.service';
import { HttpErrorResponse } from "@angular/common/http";
import { StateService } from '@uirouter/angular'; …Run Code Online (Sandbox Code Playgroud) 假设我需要在用户发出的每个请求中包含GroupId参数,但我不想修改每个服务调用以包含它.是否可以将GroupId自动附加到所有请求,无论是POST还是GET查询字符串?
我一直在研究拦截器request功能,但无法弄清楚如何进行更改
**编辑**
下面的当前工作样本是Morgan Delaney和haimlit建议的组合(我认为无论如何它都是一个组合).基本思想是,如果请求是POST,请修改config.data.对于GET,请修改params.到目前为止似乎工作.
还不清楚提供者系统如何在Angular中工作,所以我不确定在这里修改data.params属性是否完全合适.
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(['$rootScope', '$q', 'httpBuffer', function ($rootScope, $q, httpBuffer) {
return {
request: function (config) {
if (config.data === undefined) {
//Do nothing if data is not originally supplied from the calling method
}
else {
config.data.GroupId = 7;
}
if (config.method === 'GET') {
if (config.params === undefined) {
config.params = {};
}
config.params.GroupId = 7;
console.log(config.params);
}
return config;
}
};
} ]);
} …Run Code Online (Sandbox Code Playgroud) 我有一个带有工厂的配置模块,在应用程序初始化时执行(APP_INITIALIZER)
export function ConfigFactory(config: ConfigService) {
const res = () => config.load();
return res;
}
...
{
provide: APP_INITIALIZER,
useFactory: ConfigFactory,
deps: [ConfigService],
multi: true
}
Run Code Online (Sandbox Code Playgroud)
如果我在页面/组件上打印数据,一切正常。
问题是当我尝试在从 HttpInterceptor 调用的服务中使用配置时:
{
provide: HTTP_INTERCEPTORS,
useClass: TokenInterceptor,
multi: true
},
Run Code Online (Sandbox Code Playgroud)
拦截器:
constructor(private authenticationService: AuthenticationService) {}
intercept(request: HttpRequest<any> , next: HttpHandler): Observable<HttpEvent<any>> {
this.authenticationService.getAccessToken().subscribe((token: string) => { this.accessToken = token.toString(); });
this.authenticationService.getCurrentUser().subscribe((currentU: string) => { this.currentUser = currentU.toString(); });
if (this.accessToken) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${this.accessToken}`,
actor: this.currentUser,
// …Run Code Online (Sandbox Code Playgroud) configuration angular-http-interceptors angular angular-lifecycle-hooks
我对这句话有点困惑
return $q.reject(response);
Run Code Online (Sandbox Code Playgroud)
在responseError拦截器内部.
我已经阅读了关于webdeveasy的文章和关于角度文档的文章,但他们没有帮助.
这是我的代码(供参考):
(function () {
"use strict";
angular.module('xyz').factory('errorResponseInterceptor', ['$q', 'toaster', function ($q, toaster) {
return {
...
...
...
responseError: function (response) {
...
...
//some logic here
...
...
if (response.status == 500) {
toaster.error({ title: "", body: response.statusText });
return $q.reject(response);//what does this statement does and why do we need to put it here?
}
return response;
}
};
}]);
}());
Run Code Online (Sandbox Code Playgroud)
我的问题是:
return $q.reject(response)?我使用HttpClient并创建此拦截器以添加jwt令牌.每一件工作都很完美,但我的做法很糟糕.我在HttpClient拦截器中使用Http.如果我改变
private http: Http,
Run Code Online (Sandbox Code Playgroud)
至
private http: HttpClient
Run Code Online (Sandbox Code Playgroud)
我得到这个循环错误
Cannot instantiate cyclic dependency! InjectionToken_HTTP_INTERCEPTORS ("[ERROR ->]")
Run Code Online (Sandbox Code Playgroud)
任何想法我怎样才能使它工作?
import {Injectable} from "@angular/core";
import {HttpEvent, HttpHandler, HttpInterceptor} from "@angular/common/http";
import {HttpRequest} from "@angular/common/http";
import {Observable} from "rxjs/Observable";
import {Http} from "@angular/http";
import {SiteService} from "../services/site.service";
import {Router} from "@angular/router";
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(
private http: Http,
private router: Router,
private siteService: SiteService
) {}
refreshToken() {
return this.http.get(this.siteService.apiDomain() + '/api/token?token=' + localStorage.getItem('JWToken'), {})
.map((response: any) => …Run Code Online (Sandbox Code Playgroud) 在我的角度应用程序中,我看到chrome(取消)api调用太快了.我还有一个HttpInterceptor,如果请求没有完成,它会在500ms后触发每个HttpClient请求的加载指示符.但是,对于获取(取消)的请求,似乎没有任何新事件随后隐藏我的加载指示器.
有没有办法在HttpInterceptor中检测"已取消"的请求,以便我可以再次隐藏我的加载指示器?
export class GlobalHttpInterceptor implements HttpInterceptor {
constructor(
private sessionService: SessionService,
private loadingService: LoadingService
) { }
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
setTimeout(() => {
if (showLoading) {
this.loadingService.show();
}
}, 500);
let showLoading = true;
if (this.sessionService.headers.length > 0) {
for (const x of this.sessionService.headers) {
req = req.clone({
headers: req.headers.set(x.key, x.value)
});
}
}
return next.handle(req)
.do(
(response) => {
if (response instanceof HttpResponse) {
showLoading = false;
this.loadingService.hide();
}
},
(error) => { …Run Code Online (Sandbox Code Playgroud) 我是 angular 的新手,正在尝试设置 HTTP 授权标头。到目前为止,如果令牌有效,我可以为所有 API 设置授权标头。我想要的是仅为某些 API 设置标头,即使令牌可用。
@NgModule({
declarations: [AppComponent],
imports: [
HttpClientModule
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true },
]
})
Run Code Online (Sandbox Code Playgroud)
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { AuthenticationService } from '@/_services';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private authenticationService: AuthenticationService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add authorization header with jwt …Run Code Online (Sandbox Code Playgroud) 我有一个带有 HttpInterceptor 的 Angular 应用程序,它捕获 http 错误以显示一些对话框,这对我的所有应用程序都是通用的。
我想禁用某些特定调用的拦截器,但我更喜欢禁用我调用 http 的默认行为,而不是将异常写入拦截器。有人发现过这个问题吗?
如果需要,我可以用一个例子更具体。
问候
戴维德
angular ×6
angularjs ×3
javascript ×2
angular5 ×1
httpclient ×1
interceptor ×1
lazy-loading ×1
routes ×1
typescript ×1