jQuery $ .ajax调用同步执行而不是在调用WCF服务时同时执行

Sco*_*ott 11 asp.net ajax jquery

我有一个Web应用程序,其中包含一个页面,其中包含一个包含数百个字段的表单.更改任何字段会触发jQuery $ .ajax调用回服务器,以确定是否需要根据其新值将任何其他字段添加到表单中.换句话说,当一个字段发生变化时,它会检查是否需要将任何依赖字段添加到表单中.

这个过程有一些复杂性,因此,有时这些检查可能需要几秒钟.

问题是,如果一个字段位于其$ .ajax调用的中间,并且我在等待第一个字段完成时尝试更改另一个字段,则UI被阻止,我无法在页面上执行任何操作,直到第一次通话完成.就像UI一次只能处理一个$ .ajax调用一样.这是$ .ajax调用的副本:

$.ajax({
        type: "POST",
        async: true,
        url: serviceUrl,
        data: JSON.stringify(data),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        processdata: true,
        success: serviceSuccess,
        error: serviceFailed
    });
Run Code Online (Sandbox Code Playgroud)

serviceSuccess回调有很多复杂的代码更新UI,但我删除了所有的代码中它和问题仍然存在.我认为这与回调无关,因为它似乎在调用完成之前发生,但为了确定,我试了一下.

有没有人在使用jQuery $ .ajax之前听说过这样的事情?

编辑:我注意到从$ .ajax调用返回的响应大小约为130k.

编辑2: $ .ajax调用正在调用WCF服务.类定义现在看起来像这样:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class ReviewDataService : IReviewDataService, IReadOnlySessionState 
Run Code Online (Sandbox Code Playgroud)

解决方案:所以杰森绝对指出了我正确的方向.事实上,我的问题是由于ASP.NET会话锁定.为了解决这个问题,我必须从源自我的WCF服务的调用中消除调用堆栈中任何地方的Session的使用.另外,我将AspNetCompatibilityRequirementsMode设置为AspNetCompatibilityRequirementsMode.NotAllowed,并在web.config中的serviceHostingEnvironment元素中设置aspNetCompatibilityEnabled ="false".

这导致WCF在尝试访问Session时抛出错误,并且我将重构每个实例,以便它们不依赖于会话.之后,我的WCF调用开始并发运行而不是同步运行.

Jas*_*ted 9

如果您使用的是ASP.NET,则会在Session对象上使用读/写锁.这使得AJAX请求串行化.

在ASP.NET中,您可以拥有实现IReadOnlySessionState的IHttpHandlers,它不会对Session进行读/写锁定.不知道你正在使用什么环境.

编辑1

这篇文章似乎表明WCF服务不允许您灵活地解锁会话:

如何强制IIS托管的WCF或ASMX [webservice]只读取会话对象?

编辑2

设置不会锁定Session对象的IHttpHandler.

Web.config文件

<configuration>
    <connectionStrings>
    </connectionStrings>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
    <system.webServer>
        <httpProtocol>
            <customHeaders>
                <add name="Access-Control-Allow-Origin" value="*" />
            </customHeaders>
        </httpProtocol>
        <modules runAllManagedModulesForAllRequests="true" />
        <handlers>
            <add name="MyProvider" path="MyProvider.aspx" verb="*" type="MyNamespace.MyProvider" resourceType="Unspecified" />
        </handlers>
    </system.webServer>
</configuration>
Run Code Online (Sandbox Code Playgroud)

MyProvider.cs

using System;
using System.Web;
using System.Web.SessionState;

namespace MyNamespace
{
    public class MyProvider : IHttpHandler, IReadOnlySessionState
    {
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果要创建接收和返回JSON对象的提供程序,可以为Request和Response创建类,然后可以像下面这样设置处理程序:

MyProvider.cs(处理JSON对象)

using System;
using System.Runtime.Serialization.Json;
using System.Web;
using System.Web.SessionState;

namespace TestWebsite
{
    public class MyProvider : IHttpHandler, IReadOnlySessionState
    {
        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            var response = new Json.Response();
            try
            {
                var requestSerializer = new DataContractJsonSerializer(typeof(Json.Request));
                var request = (Json.Request)requestSerializer.ReadObject(context.Request.InputStream);

                // ...
            }
            catch (Exception ex)
            {
                response.Error = ex.ToString();
            }

            try
            {
                var responseSerializer = new DataContractJsonSerializer(typeof(Json.Response));
                context.Response.ContentType = "application/json";
                responseSerializer.WriteObject(context.Response.OutputStream, response);
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)