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

Angular ngOnInit中GET请求触发两次的问题排查

Angular ngOnInit发起请求导致后端收到两次请求的原因分析

问题现象

在Angular组件的ngOnInit钩子中发起带Token的GET请求时,Node+Express后端会收到两次请求:

  • 首次请求:无Token,请求头的user-agent为node
  • 第二次请求:携带正确Token,请求头为浏览器标识
    使用Postman发起请求则无此问题,仅收到一次带Token的请求。

Angular端代码

服务层请求代码

public async getAllIngredients(): Promise<Ingredient[]> {
    try {
      return await firstValueFrom(
        this.http.get<Ingredient[]>(
          `${environment.API_URL}/your-chef/ingredients/getIngredients`,
          {
            withCredentials: true,
          }
        )
      );
    } catch (error) {
      throw error;
    }
  }

组件初始化代码

@Component({
  selector: 'ingredients-page',
  imports: [SearchInputComponent, TranslateModule, IngredientCardComponent],
  templateUrl: './ingredients-page.component.html',
  styleUrl: './ingredients-page.component.scss',
})
export class IngredientsPageComponent implements OnInit {
  public ingredients: Ingredient[] = [];

  constructor(private ingredientService: IngredientService) {}

  public async ngOnInit(): Promise<void> {
    try {
      console.log('entering the function');
      this.ingredients = await this.ingredientService.getAllIngredients();
    } catch (error) {
      console.log('function error');
      throw error;
    }
  }
}

Node+Express后端代码

Token验证中间件

const isAuthenticated = (
  req: Request,
  res: Response,
  next: NextFunction
): void => {
  try {
    req.session = {};

    // 排除无需验证的登录/注册路由
    const excludedRoutes: string[] = ["/user/login", "/user/register"];
    if (excludedRoutes.includes(req.path)) {
      return next();
    }

    console.log(req.method);

    // 跳过checkToken路由的验证(登录时已设置会话)
    if (req.path !== "/user/checkToken") {
      const data: JwtPayload | string = verifyToken(req.cookies.access_token);
      req.session.user = data as IUserSession;
    }

    next();
  } catch (error: any) {
    if (error.code === ERRORS.USER.INVALID_TOKEN.code) {
      res.status(error.status).send({ message: error.message });
    } else {
      res.status(500).send({ message: "Error when validate authentication" });
    }
  }
};

CORS与中间件配置

app.use(
  cors({
    origin: process.env.FRONT_END_HOST,
    credentials: true,
  })
);

app.use(isAuthenticated);

两次请求头对比

首次请求(无Token)

{
  "host": "localhost:3000",
  "connection": "keep-alive",
  "accept": "application/json, text/plain, */*",
  "accept-language": "*",
  "sec-fetch-mode": "cors",
  "user-agent": "node",
  "accept-encoding": "gzip, deflate"
}

第二次请求(带Token)

{
  "host": "localhost:3000",
  "connection": "keep-alive",
  "sec-ch-ua-platform": "\"Windows\"",
  "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
  "accept": "application/json, text/plain, */*",
  "sec-ch-ua": "\"Chromium\";v=\"134\", \"Not:A-Brand\";v=\"24\", \"Google Chrome\";v=\"134\"",
  "sec-ch-ua-mobile": "?0",
  "origin": "http://localhost:4200",
  "sec-fetch-site": "same-site",
  "sec-fetch-mode": "cors",
  "sec-fetch-dest": "empty",
  "referer": "http://localhost:4200/",
  "accept-encoding": "gzip, deflate, br, zstd",
  "accept-language": "es,es-ES;q=0.9,ca;q=0.8,en;q=0.7",
  "cookie": "access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2Nzc1N2YwZGZlYzMxZDgzMWE3OWQ2ZGQiLCJpYXQiOjE3NDE5NTIwMzAsImV4cCI6MTc0MTk1OTIzMH0.hrOWu0WwxX2d7zNqnv1XPeGKw9tAz6FHgcV1gIpQJ3Q",     
  "if-none-match": "W/\"128-RGyy7TUC0nG6pCSxdFRvDFMWJbo\""
}

排查情况

  • 仅Angular开发服务器控制台可见重复请求,浏览器控制台无异常,且ngOnInit内的日志仅打印一次
  • 将请求改为按钮触发(用户交互触发)时,无重复请求
  • 调整CORS配置无法解决问题

原因分析

核心原因是你的Angular应用启用了服务器端渲染(SSR):

  1. 在开发环境中,SSR会先在服务器端(Node进程)渲染组件,此时ngOnInit会在服务器端执行,发起一次请求——由于是Node进程发起,没有浏览器的Cookie环境,所以请求不带Token,user-agent为node。
  2. 服务器端渲染完成后,页面发送到浏览器,客户端进行**水合(Hydration)**时,组件的ngOnInit会再次执行,发起第二次请求——此时是浏览器环境,携带了Cookie中的Token,请求头为浏览器标识。

而按钮触发的请求属于用户交互,仅在客户端执行,不会触发服务器端的渲染请求,因此不会出现重复请求的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 20:35:55