代码之家  ›  专栏  ›  技术社区  ›  Jhong

JavaScript/jQuery:如何确保跨域点击跟踪事件在用户离开页面之前成功?

  •  1
  • Jhong  · 技术社区  · 14 年前

    我使用jQuery的.live()绑定到页面上所有链接元素的mousedown事件,过滤该事件,然后在返回true之前向后端服务器发出一个带有各种数据的伪ajax请求,以便触发链接操作:

    $("#contentarea a").live("mousedown", function(ev) {
        //
        // detect event, find closest link, process it  here
        //
        $.ajax({
            url: 'my-url',
            cache: false,
            dataType: 'jsonp',
            jsonp: 'cb',
            data: myDataString,
            success: function() {
                // silence is golden -- server does send success JSONP but 
                // regardless of success or failure, we allow the user to continue
            }
        });
    
        return true; // allow event to continue, user leaves the page.
    }
    

    正如你可能从上面猜到的,我有几个限制:

    • 后端跟踪服务器与调用页位于不同的子域上。我绕不过去了。这就是为什么我使用JSONP(和GET)而不是POST的AJAX。我无法实现AJAX代理,因为web服务器没有脚本的出站网络访问权限。
    • 后端是IIS/ASP(同样是一个约束——不问!),因此,我不能立即分叉后端进程或以其他方式终止响应,而是像在更好的平台上一样继续处理

    然而,它并不可靠——对于大量的链接,尤其是目标设置为“\u top”的非站点链接,它们不会出现。如果在新的选项卡或窗口中打开了链接,则它将注册为OK。

    (a) 请求从未及时发送到后端;或

    我怀疑(b),因为服务器的延迟非常快,而且许多链接注册正常。如果我在事件触发后弹出一个警报,或者将返回值设置为false,则单击“确定”。

    Q :如果我向ASP发出POST请求,效果会更好吗?如果(b)是罪魁祸首,那么POST和GET的行为会有所不同吗?如果是这样,我可以使用一个隐藏的iframe/表单来发布数据。然而,我怀疑这会更慢,更笨重,可能仍然没有及时。我无法监听请求是否完成,因为它是跨域的。

    Q :在GET请求被触发后,我是否可以在脚本中添加一个延迟?如何以单线程方式执行此操作?我需要从函数中返回true,以确保最终触发默认事件,因此不能使用setTimeout()。一个等待“成功”的紧密循环是否会启动并设置一些可变工作?我担心这会使事情冻结太多,反应会变慢。我假设jQuery delay()插件也只是一个循环?

    或者是我没想到的其他事情可能是罪魁祸首?

    我不需要防弹的可靠性。如果所有链接在95%的时间里都是可捕获的,那就好了。然而现在,有些链接是100%可捕获的,而有些是不可捕获的——这并不能满足我的要求。

    提前谢谢。

    3 回复  |  直到 14 年前
        1
  •  0
  •   Igor Zevaka    14 年前

    我将尝试从链接事件处理程序返回false,记住URL,并仅在JSONP请求成功时导航离开。希望不会增加太多延迟。考虑到你在互联网上,这可能是好的。

        2
  •  0
  •   kingjeffrey    14 年前

    我会尝试另一种方法。您可以绑定到不同的事件,如:

    $(window).unload(function(event) {
      // tracking code here
    });
    
        3
  •  0
  •   Jhong    14 年前

    简单的回答是:没有可靠的方法可以通过GET请求跨域执行此操作。我尝试了各种各样的方法,包括存储事件和尝试稍后重播事件,以及各种各样的黑客尝试让它工作。

    最后,我让步了,使用了一个动态创建的表单来发布结果,并将目标设置为一个隐藏的iFrame。

    那个

    我现在很懊恼,我没有先尝试这个选择。