You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

并行Promise场景下Token刷新拦截器的awaitingPromise状态疑问

401响应拦截器的并行请求状态问题

我在项目中实现了一个response-interceptor,用来捕获状态码为401的响应,之后请求新的JWT Token并重试原请求。

完整代码如下:

export class TokenFlushInterceptor extends TokenRefreshInterceptor {
    private awaitingPromise: Promise<any> | null;

    constructor() {
        super();

        this.awaitingPromise = null;
    }

    private async retry(response: Response, requestOptions: RequestInit, token: string): Promise<Response> {
        return fetch(response.url, {
            ...requestOptions,
            headers: {
                ...requestOptions!.headers,
                Authorization: `Bearer ${token}`,
            },
        });
    }

    public async intercept(response: Response, requestOptions?: RequestInit): Promise<Response> {
        if (AUTH_RESPONSE_CODES.UNAUTHORIZED === response.status) {
            if (this.awaitingPromise) {
                const newToken = await this.awaitingPromise;

                const retryRequest = await this.retry(response, requestOptions!, newToken);

                this.awaitingPromise = null;

                return retryRequest;
            }

            const store = ReduxService.serverReduxStore;
            if (!store) {
                return response;
            }

            this.awaitingPromise = store.dispatch(flushToken);
            const newToken = await this.awaitingPromise;


            const retryRequest = await this.retry(response, requestOptions!, newToken);

            this.awaitingPromise = null;
            return retryRequest;
        }

        return response;
    }
}

我的设计思路是把flushToken请求的Promise存在类字段awaitingPromise中,用来处理并行请求的场景:当另一个并行请求返回401时,会等待flushToken的Promise完成后再重试自身。

但我发现这段代码存在逻辑问题,尤其是以下部分:

this.awaitingPromise = store.dispatch(flushToken);
const newToken = await this.awaitingPromise;
this.awaitingPromise = null;

const retryRequest = await this.retry(response, requestOptions!, newToken);

this.awaitingPromise = null;
return retryRequest;

假设有两个异步请求通过Promise.all执行:

  1. X请求先收到401,拦截器将awaitingPromise设为flushToken请求的Promise(此时Y请求仍处于pending状态);
  2. X请求开始重试,此时Y请求完成并收到401,进入以下代码分支:
if (this.awaitingPromise) {
    const newToken = await this.awaitingPromise;
    this.awaitingPromise = null;

    const retryRequest = await this.retry(response, requestOptions!, newToken);

    this.awaitingPromise = null;

    return retryRequest;
}

此时Y请求判断if (this.awaitingPromise)时,这个字段还持有X请求发起的flushToken Promise,但X请求的上下文已经把awaitingPromise设为null了。

我的疑问是:当Y请求进入if分支后,awaitingPromise的值会是null吗?毕竟判断if条件时flushToken还在pending,但进入分支后flushToken已经完成,且awaitingPromise已经被X请求的代码设为null了。

内容的提问来源于stack exchange,提问作者Evgeniy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 18:05:23