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

.NET Core控制器中CancellationToken突然变为true的排查求助

问题根源分析

你的问题核心是异步代码执行顺序逻辑错误,再加上偶发的请求速度差异导致了现象不稳定:

  1. Angular的HTTP请求是异步非阻塞操作,subscribe内部的回调函数只会在请求响应返回后才执行,但你把location.reload()放在了subscribe外部的同步代码块中。虽然代码里加了isDelete/isAdd/isUpdate的判断,但这些变量的赋值是在异步回调里,同步判断代码会在请求还未完成时就执行——此时变量还是初始的false,理论上不会触发刷新,但如果页面刷新逻辑意外执行(比如判断逻辑失效、误删条件),浏览器会立即终止所有未完成的HTTP请求,后端的CancellationToken就会被触发变为true。
  2. 偶发正常的原因:当本地调试时,后端接口在本地运行,请求响应速度极快,异步回调可能在页面刷新代码执行前刚好完成,此时请求已经处理完毕,页面刷新不会影响结果,所以看起来一切正常。这就是为什么问题有时会“自行消失”。

修复方案

方案1:将页面刷新逻辑移到异步回调内部

确保只有当请求成功完成后才执行页面刷新,避免终止未完成的请求:

修复后的deleteItems方法:

deleteItems(): void {
    const itemsToDelete = this.checkitems.map((item) => ({
      uicp: item.uicp,
      dqcCode: item.dqcCode,
      dqcDescription: item.dqcDescription,
      task: Object.keys(item.tasks)
        .filter((task) => item.tasks[task])
        .join(','),
      remark: item.remark,
      timestamp: item.lastUpdate,
    }));

    console.log(itemsToDelete);

    this.dataService.deleteData(itemsToDelete).subscribe((response) => {
      console.log('Items deleted:', response);
      if (response.status === 200) {
        this.tableData = this.tableData.filter(
          (item) => !this.checkitems.includes(item)
        );
        this.checkitems = [];
        // 请求成功后再刷新页面
        location.reload();
      }
    }, (error) => {
      // 新增错误处理,避免请求失败后无反馈
      console.error('删除失败:', error);
    });
}

修复后的saveItems方法(合并并发请求逻辑):

saveItems(): void {
    const requests: Observable<any>[] = [];
    const newItems = this.checkitems
      .filter((item) => item.isNew)
      .map((item) => ({
        uicp: item.uicp,
        dqcCode: item.dqcCode,
        dqcDescription: item.dqcDescription,
        task: Object.keys(item.tasks)
          .filter((task) => item.tasks[task])
          .join(','),
        remark: item.remark,
      }));

    const updatedItems = this.checkitems
      .filter((item) => !item.isNew)
      .map((item) => ({
        uicp: item.uicp,
        dqcCode: item.dqcCode,
        dqcDescription: item.dqcDescription,
        task: Object.keys(item.tasks)
          .filter((task) => item.tasks[task])
          .join(','),
        remark: item.remark,
        timestamp: item.lastUpdate,
      }));

    if (newItems.length > 0) {
      requests.push(this.dataService.addData(newItems));
    }
    if (updatedItems.length > 0) {
      requests.push(this.dataService.updateData(updatedItems));
    }

    if (requests.length > 0) {
      forkJoin(requests).subscribe(
        (responses) => {
          this.checkitems.forEach((item) => {
            item.isNew = false;
            item.selected = false;
          });
          this.checkitems = [];
          // 所有请求完成后再刷新页面
          location.reload();
        },
        (error: HttpErrorResponse) => {
          console.error('保存失败:', error.message);
        }
      );
    }
}

方案2:用async/await简化异步逻辑

将Observable转换为Promise,用async/await让代码逻辑更直观:

import { firstValueFrom } from 'rxjs';

async deleteItems(): Promise<void> {
    const itemsToDelete = this.checkitems.map((item) => ({
      uicp: item.uicp,
      dqcCode: item.dqcCode,
      dqcDescription: item.dqcDescription,
      task: Object.keys(item.tasks)
        .filter((task) => item.tasks[task])
        .join(','),
      remark: item.remark,
      timestamp: item.lastUpdate,
    }));

    console.log(itemsToDelete);

    try {
        const response = await firstValueFrom(this.dataService.deleteData(itemsToDelete));
        if (response.status === 200) {
            this.tableData = this.tableData.filter(
              (item) => !this.checkitems.includes(item)
            );
            this.checkitems = [];
            location.reload();
        }
    } catch (error) {
        console.error('删除失败:', error);
    }
}

额外注意事项
  • 永远不要在HTTP请求未完成时执行页面刷新、路由跳转等操作,这些操作会直接终止当前页面的所有未完成请求,触发后端CancellationToken。
  • 必须添加错误回调,避免请求失败后无任何反馈,方便快速排查问题。
  • 处理多并发请求时,使用forkJoin合并Observable,确保所有请求都完成后再执行后续操作,避免部分请求未完成就刷新页面。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 02:50:00