如何取消AJAX长期运行的MVC操作客户端(javascript)

How do you cancel an AJAX long running MVC action client side (in javascript)?

本文关键字:MVC 客户端 javascript 运行 操作 何取消 取消 AJAX      更新时间:2023-09-26

我有一个长时间(4-10秒)的MVC操作,它通过AJAX调用运行报告。当它运行时,用户可以更改参数并运行其他东西,所以我在发出另一个请求之前取消了AJAX请求。

因此,例如(例如在jQuery中,但问题无论如何都会发生):

// If we have an active request and it's not complete
if(dataRequest && dataRequest.readyState != 'complete') 
{
    dataRequest.abort();
}
dataRequest = $.ajax(...);

客户端这似乎工作正常,但被取消的请求仍在服务器上运行。例如,如果报告需要10秒,而我取消一个并启动另一个,那么第二个请求需要20秒。

我认为这是由于会话级别锁定:

[If]对同一会话发出两个并发请求(通过使用相同的SessionID值),则第一个请求获得对会话信息。第二个请求仅在第一个请求完成。

因此,在第一个请求完成之前,第二个请求无法访问会话。使用异步MVC操作似乎无法解决这一问题,因为该操作仍然需要能够对会话进行更改。

是否可以在不使用AsyncController[SessionState(SessionStateBehavior.ReadOnly)]的情况下停止一个动作并开始下一个动作?

如果不是,两者都需要?

[SessionState(SessionStateBehavior.ReadOnly)]或完全禁用会话足以允许从同一会话并发访问控制器操作。因此,第二个请求(来自同一会话)不需要等待第一个请求完成后再进行处理。就取消服务器上的第一个操作而言,这将更加困难。您必须将每个任务关联一个唯一的id,并且在启动新任务时将此任务id返回给客户端。然后,当您通过调用.abort()取消客户端上的AJAX请求时,您可以向其他控制器操作激发另一个AJAX请求,并向其传递唯一的任务id。此控制器操作本身将设置一些公共标志,指示要停止的第一个操作。

TPL有内置的取消支持,您可以考虑简化它,以避免2之间的共享数据结构来同步它们。

事实证明,完整的答案需要两件事:

首先(感谢Darin的确认)会话基本上锁定了要一个接一个执行的页面。进一步的调查表明,这是ASP.Net会话的一个更普遍的问题——它们无法处理乐观并发。

其次,被取消的请求需要检查客户端是否仍处于连接状态。有些情况下,你可能想继续(比如火灾并忘记ASP操作),但在这种情况下,如果客户不再等待报告,我们就没有必要继续处理它。

这可作为响应的属性:this.Response.IsClientConnected

因此,为了在jQuery请求时有效地取消服务器端操作,我必须编写自己的会话处理程序,并添加针对this.Response.IsClientConnected的定期检查。

.abort()只是客户端取消。如果您想在服务器端监视它,最好的方法之一是轮询IsClientConnected属性,它会告诉您ajax通信的状态。