Angular 如何在 HTTP 拦截器中阻止某些 HTTP 请求
How to hold off certain HTTP requests at HTTP Interceptor in Angular
我有一个Angular代码,背后的故事是这样的。我有 3 个 HTTP 调用,在一个调用中我需要一个特殊的 header (X),这是其他两个 HTTP 调用所需要的,我无法控制这些调用的执行。因此,当需要 X header 的 HTTP 调用在给我 X header 的 HTTP 调用之前进行时,我如何才能推迟调用并让特定的 HTTP 调用继续并获取 X header 并使用附加到其余 HTTP 调用的 X header 继续其余调用?看起来我正在尝试创建一个 HTTP 调用 queue 直到我得到 X header 并再次继续其余的调用。一些帮助将不胜感激。代码如下
模板:
<button class="btn btn-primary" (click)="do()"> Do </button>
App.ts 文件
export class AppComponent {
constructor(private dataService: DataService) {}
public do(): void {
this.dataService.first().subscribe();
this.dataService.second().subscribe((res) => {
this.dataService.third().subscribe();
});
}
}
data-service.ts 有 3 个 HTTP 调用
const httpOptions1 = {
headers: new HttpHeaders({ 'A': 'A' })
};
const httpOptions2 = {
headers: new HttpHeaders({ 'X': 'X' })
};
const httpOptions3 = {
headers: new HttpHeaders({ 'B': 'B' })
};
@Injectable()
export class DataService {
private apiUrl = 'https://jsonplaceholder.typicode.com/posts';
constructor(private http: HttpClient) {}
public first(): Observable<any> {
console.log('Call One')
return this.http.get(`${this.apiUrl}`, httpOptions1);
}
public second(): Observable<any> {
console.log('Call Two')
return this.http.get(`${this.apiUrl}`, httpOptions2);
}
public third(): Observable<any> {
console.log('Call Three')
return this.http.get(`${this.apiUrl}`, httpOptions3);
}
}
这是我的 X header 的第二个调用,从拦截器我想做的是当 first()
调用结束时,我想保持它添加并让second()
调用 go 并获取 X header 然后 re-run 从拦截器级别调用 first()
。
下面是拦截器的代码
private pocessed: boolean = false;
private queue: any[] = [];
constructor() {}
public intercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<any> {
/**
* Filter a certain http call with a certain X http header where this call provides a new header
* to be appended to all other http calls
*/
if (req.headers.has('X')) {
return delegate.handle(req).do((event) => {
if (event.type === HttpEventType.Response) {
// new header data acquired; hence the boolean turned to true
this.pocessed = true;
}
});
} else if (this.pocessed) {
/**
* if new header data acquired, append the new header to the rest of the calls
*/
if (this.queue.length > 0) {
// append header data to previous http calls
this.queue.forEach(element => {
let request = new HttpRequest(element.req['method'], element.req['url'], element.req['body'], {
headers: element.req['headers'],
reportProgress: true,
params: element.req['params'],
responseType: element.req['responseType'],
withCredentials: element.req['withCredentials']
});
// this.fakeIntercept(request, element.next);
});
}
// if new header data acquired, append the header to the rest of the calls
req = req.clone({ setHeaders: { 'X': 'X' } });
return delegate.handle(req).do((event) => console.log(event));
} else {
/**
* these http calls need X header but the call to get the X header hasnt gone yet
* therefor storing these calls in a queue to be used later when the header arrives
*/
this.queue.push({req: req, next: delegate});
return Observable.empty<any>();
}
}
fakeIntercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<any> {
req = req.clone({ setHeaders: { 'X': 'X' } });
return delegate.handle(req);
}
如果你们需要任何说明,请在评论中联系我。如果您看到我在这里做错了什么,请与我分享。欢迎对代码进行任何改进。
我找到了一个解决方案,它对我的 atm 非常有用。我正在使用 SUbject 流来模仿 Queue 的行为,并让请求堆积起来,直到我从 X header http 调用中获取数据。下面是代码。希望这是有道理的。干杯!
public intercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<any> {
return Observable.create(observer => {
if (req.headers.has('X') && this.headerAcquired == false) {
this.headerAcquired = true;
const subscription = delegate.handle(req).subscribe(event => {
if (event instanceof HttpResponse) {
this.pocessed = true;
this.requestSetter({key: this.pocessed});
this.removeRequest(req);
observer.next(event);
}
},
err => {
this.removeRequest(req);
observer.error(err);
},
() => {
this.removeRequest(req);
observer.complete();
});
// remove request from queue when cancelled
return () => {
this.removeRequest(req);
subscription.unsubscribe();
};
} else {
this.requests.push(req);
this.requestGetter().subscribe(res => {
const i = this.requests.indexOf(req);
if (i >= 0) {
this.subjectInit = true;
this.requests.splice(i, 1);
req = req.clone({ setHeaders: { 'X': 'X' } });
const subscription = delegate.handle(req).subscribe(event => {
if (event instanceof HttpResponse) {
this.pocessed = true;
this.request.next(true);
this.removeRequest(req);
observer.next(event);
}
},
err => {
this.removeRequest(req);
observer.error(err);
},
() => {
this.subjectInit = false;
this.removeRequest(req);
observer.complete();
});
// remove request from queue when cancelled
return () => {
this.removeRequest(req);
subscription.unsubscribe();
this.request.unsubscribe();
};
}
});
我有一个Angular代码,背后的故事是这样的。我有 3 个 HTTP 调用,在一个调用中我需要一个特殊的 header (X),这是其他两个 HTTP 调用所需要的,我无法控制这些调用的执行。因此,当需要 X header 的 HTTP 调用在给我 X header 的 HTTP 调用之前进行时,我如何才能推迟调用并让特定的 HTTP 调用继续并获取 X header 并使用附加到其余 HTTP 调用的 X header 继续其余调用?看起来我正在尝试创建一个 HTTP 调用 queue 直到我得到 X header 并再次继续其余的调用。一些帮助将不胜感激。代码如下
模板:
<button class="btn btn-primary" (click)="do()"> Do </button>
App.ts 文件
export class AppComponent {
constructor(private dataService: DataService) {}
public do(): void {
this.dataService.first().subscribe();
this.dataService.second().subscribe((res) => {
this.dataService.third().subscribe();
});
}
}
data-service.ts 有 3 个 HTTP 调用
const httpOptions1 = {
headers: new HttpHeaders({ 'A': 'A' })
};
const httpOptions2 = {
headers: new HttpHeaders({ 'X': 'X' })
};
const httpOptions3 = {
headers: new HttpHeaders({ 'B': 'B' })
};
@Injectable()
export class DataService {
private apiUrl = 'https://jsonplaceholder.typicode.com/posts';
constructor(private http: HttpClient) {}
public first(): Observable<any> {
console.log('Call One')
return this.http.get(`${this.apiUrl}`, httpOptions1);
}
public second(): Observable<any> {
console.log('Call Two')
return this.http.get(`${this.apiUrl}`, httpOptions2);
}
public third(): Observable<any> {
console.log('Call Three')
return this.http.get(`${this.apiUrl}`, httpOptions3);
}
}
这是我的 X header 的第二个调用,从拦截器我想做的是当 first()
调用结束时,我想保持它添加并让second()
调用 go 并获取 X header 然后 re-run 从拦截器级别调用 first()
。
下面是拦截器的代码
private pocessed: boolean = false;
private queue: any[] = [];
constructor() {}
public intercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<any> {
/**
* Filter a certain http call with a certain X http header where this call provides a new header
* to be appended to all other http calls
*/
if (req.headers.has('X')) {
return delegate.handle(req).do((event) => {
if (event.type === HttpEventType.Response) {
// new header data acquired; hence the boolean turned to true
this.pocessed = true;
}
});
} else if (this.pocessed) {
/**
* if new header data acquired, append the new header to the rest of the calls
*/
if (this.queue.length > 0) {
// append header data to previous http calls
this.queue.forEach(element => {
let request = new HttpRequest(element.req['method'], element.req['url'], element.req['body'], {
headers: element.req['headers'],
reportProgress: true,
params: element.req['params'],
responseType: element.req['responseType'],
withCredentials: element.req['withCredentials']
});
// this.fakeIntercept(request, element.next);
});
}
// if new header data acquired, append the header to the rest of the calls
req = req.clone({ setHeaders: { 'X': 'X' } });
return delegate.handle(req).do((event) => console.log(event));
} else {
/**
* these http calls need X header but the call to get the X header hasnt gone yet
* therefor storing these calls in a queue to be used later when the header arrives
*/
this.queue.push({req: req, next: delegate});
return Observable.empty<any>();
}
}
fakeIntercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<any> {
req = req.clone({ setHeaders: { 'X': 'X' } });
return delegate.handle(req);
}
如果你们需要任何说明,请在评论中联系我。如果您看到我在这里做错了什么,请与我分享。欢迎对代码进行任何改进。
我找到了一个解决方案,它对我的 atm 非常有用。我正在使用 SUbject 流来模仿 Queue 的行为,并让请求堆积起来,直到我从 X header http 调用中获取数据。下面是代码。希望这是有道理的。干杯!
public intercept(req: HttpRequest<any>, delegate: HttpHandler): Observable<any> {
return Observable.create(observer => {
if (req.headers.has('X') && this.headerAcquired == false) {
this.headerAcquired = true;
const subscription = delegate.handle(req).subscribe(event => {
if (event instanceof HttpResponse) {
this.pocessed = true;
this.requestSetter({key: this.pocessed});
this.removeRequest(req);
observer.next(event);
}
},
err => {
this.removeRequest(req);
observer.error(err);
},
() => {
this.removeRequest(req);
observer.complete();
});
// remove request from queue when cancelled
return () => {
this.removeRequest(req);
subscription.unsubscribe();
};
} else {
this.requests.push(req);
this.requestGetter().subscribe(res => {
const i = this.requests.indexOf(req);
if (i >= 0) {
this.subjectInit = true;
this.requests.splice(i, 1);
req = req.clone({ setHeaders: { 'X': 'X' } });
const subscription = delegate.handle(req).subscribe(event => {
if (event instanceof HttpResponse) {
this.pocessed = true;
this.request.next(true);
this.removeRequest(req);
observer.next(event);
}
},
err => {
this.removeRequest(req);
observer.error(err);
},
() => {
this.subjectInit = false;
this.removeRequest(req);
observer.complete();
});
// remove request from queue when cancelled
return () => {
this.removeRequest(req);
subscription.unsubscribe();
this.request.unsubscribe();
};
}
});