【问题标题】:Angular 5 - how to do something like a finally block?Angular 5 - 如何做类似finally块的事情?
【发布时间】:2018-08-01 11:13:59
【问题描述】:

我正在使用 Angular 5 编写一个应用程序,在我的 http 调用之后,某些功能具有类似 finally 块的内容很重要。

我不确定如何使用 Observables 执行此操作,因为 Observable 中没有 finally 函数:http://xgrommx.github.io/rx-book/content/observable/observable_methods/index.html

code snippet:
getInfo() {

    const params = new HttpParams()
        .set('username', 'swapp')
        .set('password', "test");

    return this.http
        .get('myurl', {params: params})
        .catch(this.errorHandler);
}

【问题讨论】:

  • 为什么不使用 HttpClient 拦截器?它在发出请求之前和得到响应之后集中处理逻辑。
  • 因为我想控制每次发生的事情。我的应用中的某些页面会做与其他页面不同的事情。
  • 它终于有了:xgrommx.github.io/rx-book/content/observable/… 如果您使用的是 Rxjs6,那么它将是 this.http.get('myurl', {params: params}).pipe(finally())

标签: angular angular5 observable


【解决方案1】:

我找到了一种将 finally 块添加到 Observable 的方法。

导入'rxjs/add/operator/finally';

    return this.http
        .get(CONSTANT.ENV.prod.url.concat(endpoint), {params: params})
        .catch(this.errorHandler)
        .finally(this.handleFinally)

【讨论】:

    【解决方案2】:

    您可以为此使用intercepter

    http_intercepter.ts:

    import { Injectable, Injector } from '@angular/core';
    
    import {
        HttpEvent,
        HttpHeaders,
        HttpInterceptor,
        HttpResponse,
        HttpErrorResponse,
        HttpHandler,
        HttpRequest
    } from '@angular/common/http';
    
    
    import { AppService } from './../app.service';
    import { Observable } from 'rxjs/Observable';
    import 'rxjs/add/operator/do';
    
    
    @Injectable()
    export class MyInterceptor implements HttpInterceptor {
    
        constructor(
            private appService: AppService,
            ) {
    
        }
    
        /**
         * 
         * @param req - parameter to handle http request
         * @param next - parameter for http handler
         */
        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
            const started = Date.now();
            /**
             * Handle newly created request with updated header (if given)
             */
            return next.handle(req).do((event: HttpEvent<any>) => {
                /**
                 * Sucessfull Http Response Time.
                 */
                if (event instanceof HttpResponse) {
                    const elapsed = Date.now() - started;
                }
    
            }, (err: any) => {
                /**
                 * redirect to the error_handler route according to error status or error_code
                 * or show a modal
                 */
                if (err instanceof HttpErrorResponse) {
                    switch (err.status) {
                        case 400:
                            console.log("400 type")
                            break;
                        case 401:
                            console.log("401 type")
                            break;
                        case 404:
                            console.log("404 type");
                            break;
                        default:
                            break;
                    }
                }
            });
        }
    
    }
    

    app.module.ts:

    providers: [
            {
                provide: HTTP_INTERCEPTORS,
                useClass: MyInterceptor,
                multi: true,
            },
        ]
    

    【讨论】:

    • 但是如果我想为每个http请求控制它呢?有时我每次都想做不同的事情。
    • 在问题的上下文中,也许将finally 方法块(在错误块之后)添加到 .do() 事件?
    • 您可以为每个请求执行类似的操作。 this.http .get('myurl', {params: params}) .subscribe((resp: any)=>{console.log(resp);},(err)=>{console.log(err);} );
    • 但这只会在您的组件中处理。拦截器用于集中式异常
    • 再一次,我想要一个与 promise 中的 finally 块相同的东西。如果成功或错误,我不想再次调用相同的代码。
    【解决方案3】:

    正如@UnluckyAj 所说,您可以将 catch http 失败集中在 INTERCEPTORS 中,或者如果您想在每次调用中进行精细处理,请尝试以下操作:

    getInfo() {

    const params = new HttpParams()
        .set('username', 'swapp')
        .set('password', "test");
    
    return this.http
        .get('myurl', {params: params})
        .subscribe(this.onsuccessHandler,this.errorHandler); // FIRST function is for success SECOND for failure
    

    }

    如果你想要一个 finally 块试试:

    return Observable.defer(() => {
    
    
        const params = new HttpParams()
            .set('username', 'swapp')
            .set('password', "test");
    
    
    
           return this.http
                .get('myurl', {params: params})
                .subscribe(this.onsuccessHandler,this.errorHandler);
                .finally(() => {}               
                );
    

    【讨论】:

    • 但我想要类似于承诺中的最后一个块的东西。成功与否都执行。
    • @user1261710 它可能会有所帮助stackoverflow.com/a/48988130/6332074
    • 所以你申请 finally() 订阅??
    猜你喜欢
    • 1970-01-01
    • 2018-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多