Javascript 在重定向之前将有关已单击链接的信息发送到服务器

Javascript 在重定向之前将有关已单击链接的信息发送到服务器,javascript,jquery,Javascript,Jquery,我们正在创建一个点击跟踪应用程序,用于生成热图。我正在编写一个脚本,用户应该将它插入到他们的页面中,以便跟踪工作 它在元素上运行良好,不需要重定向或表单提交。例如,如果我单击h1或p或其他任何东西,它的工作方式完全正确。但是,如果我点击一个a,对我们服务器的请求在正常重定向之前从未发生过 在过去的几天里,我尝试了很多方法。首先,我尝试了一个普通的AJAX调用,因为这是一个跨域请求,我必须使用JSONP,但是再一次,AJAX调用在重定向之前没有时间执行。添加async:false可以解决这个问题,

我们正在创建一个点击跟踪应用程序,用于生成热图。我正在编写一个脚本,用户应该将它插入到他们的页面中,以便跟踪工作

它在元素上运行良好,不需要重定向或表单提交。例如,如果我单击
h1
p
或其他任何东西,它的工作方式完全正确。但是,如果我点击一个
a
,对我们服务器的请求在正常重定向之前从未发生过

在过去的几天里,我尝试了很多方法。首先,我尝试了一个普通的AJAX调用,因为这是一个跨域请求,我必须使用JSONP,但是再一次,AJAX调用在重定向之前没有时间执行。添加
async:false
可以解决这个问题,但它不适用于JSONP请求。因此,我决定添加一个标志变量,该变量指示继续使用重定向是安全的,并使用一个空while循环来等待,直到它在ajax回调中变为try。但是while循环阻塞了执行流,所以callback从来没有机会将该变量设置为
true
。下面是一些简化的代码:

$(document).on('click', function (e) {
    //part of the code is omitted 
    $.ajax({
        url: baseUrl,
        data: data,
        type: "get",
        dataType: "jsonp",
        crossDomain: true,
        complete: function (xhr, status,) {
            itsSafeToMoveOn = true;
        }
    });

    while(!itsSafeToMoveOn){}

    return true;
});
接下来,我尝试使用
unload
page事件等待进行中的ajax调用总数变为零(我实现了一个计数器),然后继续重定向。它在Firefox和IE中工作,但在WebKit中存在以下错误:

Error: Too much time spent in unload handler
在此之后,我意识到我不关心服务器响应,使用
img.src
作为请求将非常适合这种情况。因此,在这一点上,代码如下所示:

$(document).click(function (e) {
    //part of the code is ommited
    (new Image).src = baseUrl + '?' + data;

    if (tag === "a" || clickedElement.parents().has("a")) {
        sleep(100); 
    }

    return true;
});
这样我稍微提高了脚本的整体性能,但链接的问题保持不变。
sleep
功能似乎也在阻止执行流,请求永远不会发生

剩下的唯一想法是从事件处理程序返回
false
,然后手动重定向到单击元素的
href
,或者在表单上调用
submit()
,但这将使事情变得复杂,相信我,在不同的浏览器中调试此脚本已经是一件非常痛苦的事情


有人有其他想法吗?

如果我没弄错的话,您希望在页面卸载之前完成ajax日志,并遵循href链接。这听起来是一个很好的例子,你可以考虑在jQuery中使用。 当你的用户点击任何应该让他离开页面的东西时,只需检查你的
承诺
状态。如果没有解决,您可以在页面上抛出一个模式窗口,并要求用户等待,直到进度完成。然后,将一个新的
管道
添加到您的
延迟
,告诉它在一切完成后更改
位置href


如果是这样,请告诉我。如果是,我会详细解释。如果我没有正确理解您的需求,继续没有用

您可以将信息保存到Cookie或localStorage中的ajax请求中,并使任何将发送信息的工作程序都可以。保存到Cookie或localStorage比ajax请求更快。接下来,您可以执行以下操作:

$(document).click(function (e) {
    var queue = localStorage.getItem('requestQueue');
    queue.push(data);
    localStorage.setItem('requestQueue',queue);
});

$(function(){
  setInterval(function(){
    var queue = localStorage.getItem('requestQueue');
    while (queue.length > 0) {
      var data = queue.pop();
      $.ajax({
        ...
        success: function(){
          localStorage.setItem('requestQueue', queue);
        }
      });
    }
  },intervalToSendData);
});

因此,当用户单击链接或发送表单时,数据将保存到存储器中,在用户转到下一页后,该工作人员启动并将数据发送到服务器。

JavaScript基本上是在单线程中执行的。不可能执行回调函数,同时让无限循环等待来自它的标志变量。无限循环将占用单个执行线程,并且永远不会调用回调

最好的方法是取消事件的默认处理程序并冒泡(如果确实使用jQuery构建跟踪代码,则基本上返回false),然后执行必要的操作(如果单击了链接或触发其他默认操作,则将页面重定向到必要的地址),但是,要重新创建actiona和回调的所有可能组合,这需要大量细致的工作

另一种方法是: 1) 在事件数据中查找特定于代码的内容 2) 如果不存在,则进行AJAX调用,并在其回调中重新触发相同的元素,即使是在同一个元素上,但这次将特定位添加到偶数数据中;AJAX调用后返回false 3) 如果您的特定位存在于数据中,只需什么都不做,就可以进行默认的事件处理

然而,这两种方法都可能产生不利影响

var globalStopper = true;

$(document).on('click', function (e) {
    if (globalStopper === false)
        return true; //proceed with click if stopper is NOT set
    else {
        globalStopper = false; //release the breaks

        $.ajax({
            //blahblah
            complete: function (xhr, status,) {
                $(elem).click(); //when ajax request done - "rerun" the click
            }
        });
        return false; //DO NOT let browser process the click
    }
});
另外,请尝试添加脚本,而不是添加图像。然后将脚本添加到HEAD部分。这样,浏览器将“等待”直到加载

 $(document).on('click', function (e) {
     var scriptTag = document.createElement("script");
     scriptTag.setAttribute("type", "text/javascript");
     scriptTag.setAttribute("src", url);
     document.getElementsByTagName("head")[0].appendChild(scriptTag);
     return true;
 }

我想看看中提到的或直接链接到的navigator sendBeacon API

根据网站上的描述

sendBeacon(url,数据)-此方法满足分析和诊断代码的需求,这些代码通常在卸载文档之前尝试将数据发送到web服务器


您是否尝试过preventDefault?您的
itsSafeToMoveOn
var声明在哪里?@Jibibaraham我需要重定向,preventDefault将取消它。@sp00m在中声明,click handlerScript需要为用户透明地工作,因此我不能使用模式窗口。@maxt3r-如果您想转到其他页面,而且当前页面上还有待处理的项目,如果您让用户知道,不是更好吗?不,此脚本用于分析,客户不应该知道。而且它不会对页面性能产生太大的影响。我也有这个想法。这有点像我的备份计划,但很有可能下一页上没有我的脚本,因此缓存的请求将永远保留在cookie中。如果下一页在另一个网站上呢??