【问题标题】:Error: Type 'void' is not assignable to type 'HttpEvent<any>'错误:类型“void”不可分配给类型“HttpEvent<any>”
【发布时间】:2021-02-06 09:37:18
【问题描述】:

我想拦截 http 响应,尤其是在出现 401 之类的错误时。所以我在 toPromise 之后使用了 catch 块。但我在下面收到错误。

错误:键入'void | HttpSentEvent | HttpHeader 响应 | HttpProgressEvent |响应 | HttpUserEvent' 不可分配给类型 'HttpEvent'。 类型“void”不可分配给类型“HttpEvent”。

这是我的拦截器代码。你能说出代码有什么问题并给出解决方案吗?谢谢

import { Injectable } from '@angular/core';
import {
    HttpInterceptor,
    HttpEvent,
    HttpResponse,
    HttpErrorResponse,
    HttpRequest,
    HttpHandler,
    HttpHeaders
} from '@angular/common/http';
import { TokenService } from '../services/token.service';
import { environment } from 'src/environments/environment';
import { observable, Observable, throwError } from 'rxjs';
import { fromPromise } from 'rxjs/internal-compatibility';

@Injectable()
export class CustomHttpInterceptor implements HttpInterceptor {
    constructor(private tokenService: TokenService,
        private authService: AuthService) {
    }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return fromPromise(this.handleAccess(request, next));
    }

    private async handleAccess(request: HttpRequest<any>, next: HttpHandler): Promise<HttpEvent<any>> {
        const token = await this.tokenService.getToken();
        const lang = localStorage.getItem('pref_lang');
        
        let changedRequest = request;
       
        const headerSettings: { [name: string]: string | string[]; } = {};

        for (const key of request.headers.keys()) {
            headerSettings[key] = request.headers.getAll(key);
        }
        if (token) {
            headerSettings['Authorization'] = 'Bearer ' + token;
        }
        
        headerSettings['Content-Type'] = 'application/json';
        headerSettings['Accept-Language'] = lang;

        const newHeader = new HttpHeaders(headerSettings);
        changedRequest = request.clone({
            headers: newHeader
        });
        return next.handle(changedRequest).toPromise().catch(error => {
            console.log('HttpErrorResponse error', error);
            if (error instanceof HttpErrorResponse) {
                console.log('HttpErrorResponse error status code', error.status);
                switch ((<HttpErrorResponse>error).status) {
                    case 401:
                        return this.handle401Error(request, next);
                }
            } else {
                console.log('something went wrong error', error);
            }
        });
    }

    handle401Error(req: HttpRequest<any>, next: HttpHandler) {
    console.log('handle401Error called...');
    if (!this.isRefreshingToken) {
        this.isRefreshingToken = true;
        let cachedRequest = req;
        this.authService.getFreshAccessToken().then((res) => {
            next.handle(cachedRequest).toPromise();
        }).catch(error => {
             this.authService.logout();
        }).finally(() => {
            cachedRequest = null;
            this.isRefreshingToken = false;
        });
    }
}

}

【问题讨论】:

    标签: angular ionic-framework angular-http-interceptors


    【解决方案1】:

    我在里面放了一些cmets:

    --8<---
                if (error instanceof HttpErrorResponse) {
                    console.log('HttpErrorResponse error status code', error.status);
                    switch ((<HttpErrorResponse>error).status) {
                        case 401:
                            return this.handle401Error(request, next);
                        // here, you're missing the default-case. HttpErrorResponses other than status 401 are completely ignored and the return-type will be void, as the else-statement below is never reached
                    }
                } else {
                    // you should return something here, as not returning anything at all is the same as returning void
                    console.log('something went wrong error', error);
                }
                // the default could be to just rethrow the error to let the caller handle it. This should also remove the compiler error
                throw error;
    --8<---
    

    【讨论】:

    • 抛出错误语句后,错误消失了。但在这里我的疑问是,在 handle401Error(request, next) 方法中,我正在从服务器刷新令牌,成功后再次尝试相同的请求。那么如果我抛出错误会扰乱这个流程吗?
    • 不,它不会,因为如果您在 case 401 语句中返回基于重试逻辑的 Promise,则永远不会到达最后一个返回语句!
    • 不知何故请求没有得到重试。您能否告诉我这样做的错误和正确方法是什么。
    • 代码使用句柄 401 方法更新。你能告诉我代码有什么问题吗?谢谢
    猜你喜欢
    • 2021-09-23
    • 2020-08-24
    • 2018-04-19
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    • 2021-12-10
    相关资源
    最近更新 更多