You need to enable JavaScript to run this app. MVC下请求无法取消,点击取消后第二次请求延迟到达问题咨询
优惠活动
大模型
产品
解决方案
定价
更多

MVC下请求无法取消,点击取消后第二次请求延迟到达问题咨询

问题根因

  • 控制器参数类型错误:ASP.NET Core 默认只会将客户端断开触发的取消信号注入到CancellationToken类型参数,你当前使用CancellationTokenSource作为参数,无法正确接收到前端取消请求的信号。
  • 前端取消逻辑不完整:仅隐藏加载图标未真正终止AJAX请求,服务端仍会继续执行耗时的视图绑定逻辑;同时浏览器对同域名的并发请求有配额限制(通常为6个),未终止的旧请求占用了连接池,新请求只能排队等待,就是你遇到的等待1分钟才进入控制器的原因。
  • BindResultToPartialView方法内部未检查取消令牌,就算拿到取消信号也会跑完整个渲染流程,持续占用服务端资源。

后端修改方案

  1. 调整控制器参数类型,改为框架自动注入的CancellationToken,渲染前先检查是否已取消:
public async Task<IActionResult> Get(CancellationToken cancellationToken)
{
    var rng = new Random();
    var res = Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
    })
    .ToArray();
    // 渲染前先校验取消信号,提前终止流程
    cancellationToken.ThrowIfCancellationRequested();
    return await BindResultToPartialView(res, cancellationToken);
}
  1. 改造BindResultToPartialView方法,在耗时的绑定逻辑(比如遍历数据生成网格行)中添加取消校验:
private async Task<IActionResult> BindResultToPartialView<T>(T data, CancellationToken cancellationToken)
{
    // 入口先校验取消信号
    cancellationToken.ThrowIfCancellationRequested();
    // 遍历绑定时每轮都校验
    if (data is IEnumerable enumerableData)
    {
        foreach (var item in enumerableData)
        {
            cancellationToken.ThrowIfCancellationRequested();
            // 原有行绑定逻辑
        }
    }
    // 剩余渲染逻辑
}

前端修改方案

全局存储当前请求的实例,发起新请求或者用户点击取消按钮时,主动调用abort()终止旧请求,释放连接池配额:

原生JS实现

// 全局存储当前请求实例
let currentGetRequest = null;

// 拉取数据方法
function loadGridData() {
    // 发起新请求前先终止上一个未完成的请求
    if (currentGetRequest) {
        currentGetRequest.abort();
        currentGetRequest = null;
    }
    currentGetRequest = new XMLHttpRequest();
    currentGetRequest.open('GET', '/你的控制器名称/Get', true);
    currentGetRequest.onload = function() {
        if (currentGetRequest.status === 200) {
            // 替换局部视图的逻辑
        }
        currentGetRequest = null;
    };
    currentGetRequest.onabort = currentGetRequest.onerror = function() {
        currentGetRequest = null;
        // 隐藏加载图标的逻辑
    };
    currentGetRequest.send();
}

// 取消按钮点击事件
document.getElementById('你的取消按钮ID').addEventListener('click', function() {
    if (currentGetRequest) {
        currentGetRequest.abort();
    }
    // 隐藏加载图标的逻辑
});

jQuery AJAX实现

let currentGetRequest = null;

function loadGridData() {
    if (currentGetRequest) {
        currentGetRequest.abort();
    }
    currentGetRequest = $.ajax({
        url: '/你的控制器名称/Get',
        type: 'GET',
        success: function (res) {
            // 替换局部视图的逻辑
        },
        complete: function () {
            currentGetRequest = null;
        }
    });
}

$('#你的取消按钮ID').on('click', function() {
    if (currentGetRequest) {
        currentGetRequest.abort();
    }
    // 隐藏加载图标的逻辑
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 06:36:04