JavaScript/jQuery: How to make sure cross-domain click tracking event succeeds before the user leaves the page?(JavaScript/jQuery:如何在用户离开页面之前确保跨域点击跟踪事件成功?)
问题描述
我正在从我们公司内部网的各个页面实现点击跟踪,以添加一些急需的众包流行链接功能(过去 24 小时内您部门中最流行的链接"等)
I'm implementing click tracking from various pages in our corporate intranet in order to add some sorely needed crowd-sourced popular link features ("most popular links in your department in the last 24 hours", etc.)
我正在使用 jQuery 的 .live() 为页面上的所有链接元素绑定到 mousedown 事件,过滤事件,然后在返回之前向后端服务器发出带有各种数据的伪 ajax 请求true 以便触发链接操作:
I'm using jQuery's .live() to bind to the mousedown event for all link elements on the page, filter the event, and then fire off a pseudo-ajax request with various data to a back-end server before returning true so that the link action fires:
$("#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.
}
正如您可能从上面猜到的那样,我有几个限制:
As you can probably guess from the above, I have several constraints:
- 后端跟踪服务器与调用页面位于不同的子域中.我无法解决这个问题.这就是为什么我使用 JSONP(和 GET)而不是正确的 AJAX 和 POST.我无法实现 AJAX 代理,因为 Web 服务器没有脚本的出站网络访问权限.
- 这可能无关紧要,但为了全面披露,内容和脚本位于主要内容"iframe 内(这不会改变.我可能最终会将事件侦听器移至父框架监视它的链接和所有子内容,但第 1 步是让它在1 个子窗口"的简化情况下正常工作).父子是同一个域.
- 后端是 IIS/ASP(同样是一个约束——别问了!),所以我不能立即分叉后端进程或以其他方式终止响应,但我可以像在更好的平台
尽管如此,但在大多数情况下,该系统仍能正常工作——我点击页面上的链接,它们会非常无缝地出现在数据库中.
Despite all this, for the most part, the system works -- I click links on the page, and they appear in the database pretty seamlessly.
但它并不可靠——对于大量链接,尤其是目标设置为_top"的非站点链接,它们不会出现.如果链接在新选项卡或窗口中打开,则注册成功.
However it isn't reliable -- for a large number of links, particularly off-site links that have their target set to "_top", they don't appear. If the link is opened in a new tab or window, it registers OK.
我已经排除了脚本错误——似乎是:
I have ruled out script errors -- it seems that either:
(a) 请求永远不会及时到达后端;或
(a) the request is never making it to the back-end in time; or
(b) 请求正在发出,但 ASP 检测到客户端在不久之后断开连接,并且由于它是 GET 请求,因此没有处理它.
(b) the request is making it, but ASP is detecting that the client is disconnecting shortly afterwards, and as it is a GET request, is not processing it.
我怀疑 (b),因为服务器的延迟非常快,而且许多链接注册正常.如果我在事件触发后弹出警报,或者将返回值设置为false,则点击注册成功.
I suspect (b), since latency to the server is very fast and many links register OK. If I put in an alert pop-up after the event fires, or set the return value to false, the click is registered OK.
关于如何解决这个问题的任何建议(在我无法更改约束的情况下)?我无法使 GET 请求同步,因为它不是真正的 AJAX.
Any advice on how I can solve this (in the context that I cannot change my constraints)? I can't make the GET request synchronous as it is not true AJAX.
问:如果我向 ASP 发出 POST 请求会更好吗?如果 (b) 是罪魁祸首,那么 POST 与 GET 的行为会有所不同吗?如果是这样,我可以使用隐藏的 iframe/form 来发布数据.但是,我怀疑这会更慢,更笨重,并且可能仍然无法及时完成.因为是跨域的,所以我无法监听请求是否完成.
Q: Would it work better if I was making a POST request to ASP? If (b) is the culprit would it behave differently for POST vs GET? If so, I could use a hidden iframe/form to POST the data. however, I suspect this would be slower and more clunky, and might still not make it in time. I wouldn't be able to listen to see if the request completes because it is cross-domain.
问:我可以在 GET 请求触发后向脚本添加延迟吗?如何以单线程方式执行此操作?我需要从我的函数中返回 true,以确保最终触发默认事件,所以我不能使用 setTimeout().等待成功"触发并设置一些变量的紧密循环会起作用吗?我担心这会使事情冻结太多,响应速度会变慢.我假设 jQuery delay() 插件也只是一个循环?
Q: Can I just add a delay to the script after the GET request is fired off? How do I do this in a single-threaded way? I need to return true from my function, to ensure the default event eventually fires, so I can't use setTimeout(). Would a tight loop waiting for 'success' to fire and set some variable work? I'm worried that this would freeze up things too much and the response would be slowed down. I assume the jQuery delay() plugin is just a loop too?
或者是我没想到的其他东西可能是罪魁祸首?
Or is something else I haven't thought of likely to be the culprit?
我不需要万无一失的可靠性.如果所有链接在 95% 的时间里都是同样可捕获的,那就没问题了.但是现在,有些链接在 100% 的时间里都可以捕获,而另一些则无法捕获——这并不能达到我想要实现的目标.
I don't need bullet-proof reliability. If all links are equally catchable 95% of the time it is fine. However right now, some links are catchable 100% of the time, while others are uncatchable -- which isn't going to cut it for what I want to achieve.
提前致谢.
推荐答案
解决了!
简短的回答是:没有可靠的方法通过 GET 请求进行跨域.我尝试了各种方法,包括存储事件并尝试稍后重播事件,以及各种黑客尝试让它发挥作用.
The short answer is: there is no reliable way to do this cross-domain with a GET request. I tried all sorts, including storing the event and trying to replay the event later, and all manner of hacks to try to get that to work.
然后我尝试了紧循环,但它们也不可靠.
I then tried tight loops, and they weren't reliable either.
最后,我只是放弃并使用了一个动态创建的表单来发布结果,目标设置为隐藏的 iFrame.
Finally, I just gave in and used a dynamically created form that POSTed the results, with the target set to a hidden iFrame.
那 工作可靠——浏览器似乎在继续之前暂停以完成其 POST 请求,并且 ASP 尊重 POST.事实证明,它一点也不笨拙".当然,由于浏览器安全模型,我看不到结果……但在这种情况下没关系.
That works reliably -- it seems the browser pauses to finish its POST request before moving on, and ASP honours the POST. Turns out it's not 'clunky' at all. Sure, due to the browser security model I can't see the result... but it doesn't matter in this case.
我现在很自责,因为我没有先尝试那个选项.
I am now kicking myself that I didn't try that option first.
这篇关于JavaScript/jQuery:如何在用户离开页面之前确保跨域点击跟踪事件成功?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:JavaScript/jQuery:如何在用户离开页面之前确保跨域点击跟踪事件成功?
基础教程推荐
- 用于 Twitter 小部件宽度的 HTML/CSS 2022-01-01
- 如何使用JIT在顺风css中使用布局变体? 2022-01-01
- 直接将值设置为滑块 2022-01-01
- 如何使用TypeScrip将固定承诺数组中的项设置为可选 2022-01-01
- html表格如何通过更改悬停边框来突出显示列? 2022-01-01
- Electron 将 Node.js 和 Chromium 上下文结合起来意味着 2022-01-01
- 我可以在浏览器中与Babel一起使用ES模块,而不捆绑我的代码吗? 2022-01-01
- 自定义 XMLHttpRequest.prototype.open 2022-01-01
- Vue 3 – <过渡>渲染不能动画的非元素根节点 2022-01-01
- Chart.js 在线性图表上拖动点 2022-01-01