在Angular的HttpInterceptor中进行实际的http调用之前,调用另一个HTTP api(无拦截) [英] Call another http api (without Intercepting) before actual http call is made in Angular's HttpInterceptor

查看:146
本文介绍了在Angular的HttpInterceptor中进行实际的http调用之前,调用另一个HTTP api(无拦截)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Angular的 HttpClientModule HttpInterceptor api,现在遇到了麻烦。这是我的用例。

I'm using HttpInterceptor api of Angular's HttpClientModule and now stuck with a situation. Here is my use-case.

在我的应用程序中,如果有任何服务进行了HTTP调用,我想在它之前进行另一个静默的HTTP调用,并希望将其存储本地结果。静默通话结束后,只有我继续进行该服务的http通话并返回其结果。

In my application, if any service makes an http call, I want to make another silent http call before it, and want to store it's result locally. Once the silent call is completed, then only I'll proceed with the service's http call and will return its result.

这就是我正在做的事情。 (使用HttpInterceptor)

Here is what I'm doing. (Using HttpInterceptor)

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.url.match(/api\//)) { // api call
           http.post('/auth/silentCall', {user: 123}).subscribe(
                     (data) => {
                        console.log(data);
                        const clone = req.clone({ setHeaders: { 'Authorization ': tokenService.getToken() } });
                        return  next.handle(clone).do((event: HttpEvent<any>) => {
                            if (event instanceof HttpResponse) {
                                console.log('Service's call response');
                            }
                        }, (err: any) => {
                            if (err instanceof HttpErrorResponse) {
                                console.log('Network call err', err);
                            }
                        });
                     },
                     (err) => {
                        if (err instanceof HttpErrorResponse) {
                           return Observable.throw(err); 
                        }
                 );
                } else {
        console.log('Not an api call..It's an auth call');
       return next.handle(req); // call original auth request.
    }
}

现在,上面代码的问题是成功执行内部静默调用,但此后再也不会调用原始的api调用。因此,该服务将永远保持等待状态。

Now, problem with the above code is, it is executing internal silent call successfully, but never calls the original api call after that. So the service keeps waiting forever.

推荐答案

已更新:添加了可运行的plunkr。 https://plnkr.co/edit/WFecj8fFZ6z4G6mpLSCr?p=preview

Updated: Added a working plunkr. https://plnkr.co/edit/WFecj8fFZ6z4G6mpLSCr?p=preview

记下使用浏览器的开发工具进行的调用和添加的标题的顺序。

Take note of the sequence that the calls are being made and the headers that are being added using your browser's dev tools.

还要注意,下面的解决方案使用RxJS lettable运算符而不是标准运算符(它们不应有任何不同的行为...在代码无法编译的情况下添加此注释)

Also note that the below solution is using RxJS lettable operators instead of the standard operators (which shouldn't have any different behavior... adding this note in case the code doesn't compile)

问题的原因是在以下情况下 intercept 方法从不返回句柄调用匹配 / api

The cause of the problem is the fact that the intercept method is never returning a handle in the case that the call matches /api.

将代码更新为类似于以下内容

Update your code to something similar to the following

intercept(req: HttpRequest<any>, next: HttpHandler):Observable<HttpEvent<any>> {
    if (req.url.match(/api\//)) { // api call
           return http.post('/auth/silentCall', {user: 123}).pipe(switchMap((response) => {
               console.log('Service's call response');

               let clone = req.clone({ setHeaders: { 'Authorization ': tokenService.getToken() } });
               return  next.handle(clone);
           }), catchError((err) => {
               if(err instanceof HttpErrorResponse) {
                   console.log('Your logging here...');
                   let clone = req.clone({ setHeaders: { 'Authorization ': tokenService.getToken() } });
                   return  next.handle(clone);
               }

               return Observable.throw(err); 
           }));
    } else {
       return next.handle(req); // call original auth request.
    }
}

请注意 http.post 被平面映射以返回 next.handle()方法返回的可观察序列,或使用<$引发终止的可观察序列c $ c> Observable.throw()。

Note that the response of the http.post is being flatmaped to return the observable sequence returned by the next.handle() method or to thrown a terminated observable with Observable.throw().

还要注意,如果条件被删除,因为如果api调用失败,则捕获块被调用(如果是订阅,则调用错误处理函数)

Also note that the if condition has been removed since if the api call fails, the catch block is called (or the error handler function, in case of subscribe)

这篇关于在Angular的HttpInterceptor中进行实际的http调用之前,调用另一个HTTP api(无拦截)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆