是什么原因导致JavaScript结构在实时版本中失败但在测试中工作?

时间:2012-03-15 18:47:39

标签: json coldfusion

我在两台服务器上使用ColdFusion 8,两者都具有完全相同的ColdFusion版本和相同的设置。

我们正在CFC中创建一个结构,并使用toScript()函数将其传递给浏览器。网页上生成的JavaScript如下所示:

TrackingInfo = new Object();
TrackingInfo["child_catalog_id"] = "";
TrackingInfo["ipaddress"] = "63.123.41.14";
TrackingInfo["parent_catalog_id"] = 1642;
TrackingInfo["session_id"] = 30000390;
TrackingInfo["referral"] = "";
TrackingInfo["useragent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) G    ecko/20100101 Firefox/10.0.2";
TrackingInfo["querystring"] = "";

稍后在页面中,在JavaScript中,我们将TrackingInfo结构(ABOVE)传递给相同的CFC - 但是使用CFAJAXPROXY这是一个不同的函数:

var jro = new JS_SessionTracking();
jro.InsertSessionTrackingFunction(TrackingInfo);

在CFC中,InsertSessionTrackingFunction函数接受结构并将其输入数据库,

<!--- INSERT SESSION TRACKING FUNCTION --->
<cffunction name="InsertSessionTrackingFunction" access="remote">
    <cfargument name="TrackingInfo" required="true">
    <cfset LOCAL.TrackingInfo = ARGUMENTS.TrackingInfo>
    // DATABASE STUFF HAPPENS HERE
    <cfreturn true>
</cffunction>

在我们的开发和舞台网站中,这可以完美运行,在许多机器和许多浏览器中进行测试。它按设计和期望工作。

当我们将代码移动到生产时,它的每个方面都可以使用,最后一个函数(InsertSessionTrackingFunction)除外。我们的服务器拒绝处理从网页传递给CFC的JavaScript。 Firebug显示没有错误。不返回真实值。

什么可能导致CFC不喜欢在LIVE设置中传递给它的结构,但在开发设置中工作得很好?

另外,我尝试使用ColdFusion函数serializeJSON()在传递页面之前格式化结构。它输出到这样的页面:

LOCAL.TrackingInfo = serializeJSON(LOCAL.TrackingInfo); // serialize the structure

TrackingInfo = "{\"CHILD_CATALOG_ID\":\"\",\"IPADDRESS\":\"63.173.41.14\",\"PARENT_CATALOG_ID\":1642,\"SESSION_ID\":30000390,\"REFERRAL\":\"\",\"USERAGENT\":\"Mozilla\\/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko\\/20100101 Firefox\\/10.0.2\",\"QUERYSTRING\":\"\"}";

我将结构传递给函数并使用deserializeJSON函数来解析它:

<cfset LOCAL.TrackingInfo = deserializeJSON(LOCAL.TrackingInfo)>

尽管如此,此功能在开发和暂存中仍能正常工作,但在生产中失败。

请告诉我为什么会发生这种情况以及如何纠正这个问题。

更新

我接受了Jake Feasel的建议并在每个函数的头部添加了<cfset var LOCAL = {}>,以确保值不会浮动。虽然它似乎是CF8的好习惯,但这并没有解决问题。

以下代码在生产和我们的实时环境中运行良好。无需更改CFC即可完成此项工作。 ColdFusion根本不允许将该结构传递到该服务器上的函数中。

<script>
  <cfoutput>
        #toscript(TrackingInfo.SID, "SID")# 
        #toscript(TrackingInfo.parent_catalog_id, "Parent")#
        #toscript(TrackingInfo.child_catalog_id, "Child")#
  </cfoutput>

  // CREATE JAVASCRIPT OBJECT
  var jro = new JS_SessionTracking();
  jro.InsertSessionTrackingFunction(SID,Parent,Child); 
</script>

2 个答案:

答案 0 :(得分:2)

常见问题排查地点以查找测试与产品差异:

  1. 不同的数据(可能是导致错误的狂野角色?)
  2. Web服务器基础结构差异(反向代理导致缓存 问题;启用了不同的模块;)
  3. 浏览器设置(在测试和开发时禁用缓存页面,但未启用 PROD)
  4. 服务器配置的其他复杂性(例如不同 用于托管主页面的子域名或不同的端口 Ajax请求;这会引入Same origin policy 问题。
  5. 但是,现在我们已经在特定情况下消除了那些可能的问题来源....

    您说您的所有CF版本都是相同的,并且您使用的是CF 8.但是,您尝试使用的“本地”范围是在CF 9中引入的:

    http://forta.com/blog/index.cfm/2009/6/21/The-New-ColdFusion-LOCAL-Scope

    由于(从您的评论中)这是您看到错误的地方,我怀疑这是问题所在。

    <强>更新

    有一点值得一提的是在CF8中使用LOCAL - 使用它不会引发错误,但很可能会出现意外行为(可能就像你在这里看到的那样)。

    <cffunction name="foo">
        <cfset local.bar = "Hello World">
    
        <cfreturn local.bar>
    </cffunction>
    

    我在CF8中测试了上面的例子,它“有效” - 它不会抛出错误。但是,它将要做的是在请求或组件的变量范围中创建一个名为“local”的新结构(取决于函数所在的位置)。然后,它将在该上下文中全局可用(如果您正在缓存CFC实例,则可能是持久的)。如果这是CFC的共享缓存实例,则很可能如果您同时从多个客户端访问它(如果函数长时间运行,则特别明显),那么您将在每次请求时覆盖该局部变量。 这只是在开发或登台时不会显而易见的问题,因为一次访问该网站的用户较少。此外,如果您在不同的功能中使用相同的名称,一个人可能会与你正在运行的实例发生冲突,导致谁知道出现了什么样的问题。

    最好的选择是通过添加一行来更新您的功能:

    <cffunction name="InsertSessionTrackingFunction" access="remote">
        <cfargument name="TrackingInfo" required="true">
        <cfset var LOCAL = {}>
        <cfset LOCAL.TrackingInfo = ARGUMENTS.TrackingInfo>
        // DATABASE STUFF HAPPENS HERE
        <cfreturn true>
    </cffunction>
    

    这会明确地将您的本地范围限制为您的功能。

    你可能没有在firebug中看到错误,因为你可能有一些全局错误处理程序可以抑制CF错误,可能只在生产时设置为禁止。

答案 1 :(得分:1)

CF管理员中有一个名为“Prefix serialized JSON with”的设置,默认为//。如果您的测试和生产系统的设置不同,则可能会导致问题。