简体   繁体   English

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

[英]Send information about clicked link to the server before redirect

We're creating a click tracking app, that builds heatmaps. 我们正在创建一个构建热图的点击跟踪应用。 I'm writing a script which users are suppose to insert into their pages for tracking to work. 我正在编写一个脚本,用户可以将其插入到页面中以便跟踪工作。

It works fine on elements, which doesn't require a redirect or form submit. 它适用于元素,不需要重定向或表单提交。 For example, if I click on h1 or p or whatever, it works perfectly correct. 例如,如果我点击h1p或其他任何东西,它的工作方式完全正确。 But, if I click on a a , request to our server never happens before the normal redirect. 但是,如果我点击a ,对我们的服务器的请求永远不会发生在正常的重定向之前。

In the last couple of days I tried a lot of ways to do that. 在过去的几天里,我尝试了很多方法来做到这一点。 First of, I tried a normal AJAX call, since it was a cross-domain request I had to use JSONP, but again, that AJAX call did not have time to execute before the redirect. 首先,我尝试了一个普通的AJAX调用,因为它是一个跨域请求,我不得不使用JSONP,但同样,AJAX调用在重定向之前没有时间执行。 Adding async: false would have solved the problem, but it doesn't work with JSONP requests. 添加async: false可以解决问题,但它不适用于JSONP请求。 So I decided to add a flag variable which indicates that it is safe to move on with redirect and used an empty while loop to wait until it becomes try in the ajax callback. 所以我决定添加一个标志变量,表示使用重定向继续运行是安全的,并使用空的while循环等待它在ajax回调中尝试。 But the while loop was blocking the execution flow, so callback never got a chance to set that variable to true . 但while循环阻止了执行流程,因此回调从未有机会将该变量设置为true Here is some simplified code: 这是一些简化的代码:

$(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;
});

The next thing I tried is to use unload page event to wait until total ajax calls in progress would become zero (I had a counter implemented) and then to move on with redirect. 我尝试的下一件事是使用unload页面事件等待,直到正在进行的总ajax调用将变为零(我实现了一个计数器),然后继续使用重定向。 It worked in Firefox and IE, but in WebKit there was this error: 它在Firefox和IE中有效,但在WebKit中出现了这样的错误:

Error: Too much time spent in unload handler

After that I realized that I don't care about the server response and using img.src for the request would be an ideal fit for this case. 之后我意识到我不关心服务器响应,并且使用img.src来处理请求将非常适合这种情况。 So at this point code looks like this: 所以在这一点上代码看起来像这样:

$(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;
});

That way I increased the overall script performance slightly, but problem with links remains unchanged. 这样我略微提高了整体脚本性能,但链接问题仍未改变。 The sleep function appears to be also blocking the execution flow and request never happens. sleep功能似乎也阻止了执行流程,请求永远不会发生。

The only idea left is to return false from the event handler and than redirect manually to the clicked element's href or to call submit() on the form, but it will complicate things to much and believe me it's already a huge pain in the ass to debug this script in different browsers. 剩下的唯一想法是从事件处理程序返回false ,然后手动重定向到单击元素的href或在窗体上调用submit() ,但它会使事情复杂化并相信我已经是一个巨大的痛苦在不同的浏览器中调试此脚本。

Does anyone have any other ideas? 有没有人有任何其他想法?

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
    }
});

Also, instead of adding image, try adding script. 此外,尝试添加脚本,而不是添加图像。 And then add the script to the HEAD section. 然后将脚本添加到HEAD部分。 This way the browser will "wait" until it's loaded. 这样浏览器将“等待”直到它被加载。

 $(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;
 }

I would take a look at the navigator sendBeacon API mentioned in this stack overflow answer or directly linked to here . 我会看看这个堆栈溢出答案中提到的导航器sendBeacon API或直接链接到这里

From the description on the site 从网站上的描述

navigator.sendBeacon(url, data) - This method addresses the needs of analytics and diagnostics code that typically attempts to send data to a web server prior to the unloading of the document. navigator.sendBeacon(url,data) - 此方法满足分析和诊断代码的需求,这些代码通常在卸载文档之前尝试将数据发送到Web服务器。

So if I understand right, you want your ajax logs completed before the page unloads and follows a link href. 因此,如果我理解正确,您希望在页面卸载之前完成ajax日志并遵循链接href。 This sounds like a perfect case where you could consider using Deferreds in jQuery. 这听起来像是一个完美的案例,你可以考虑在jQuery中使用Deferreds

When your user clicks on anything that's supposed to take him away from the page, just check your promise status. 当您的用户点击任何应该将他带离页面的内容时,只需检查您的promise状态即可。 If it's not resolved, you could throw a modal window over the page, and ask the user to wait til the progress is complete. 如果它没有解决,你可以在页面上抛出一个模态窗口,并要求用户等待进度完成。 Then, add a new pipe to your deferred , telling it to change the location href once everything is complete. 然后,在deferred添加一个新pipe ,告诉它在一切都完成后更改location href

Let me know if this is the scenario. 如果是这种情况,请告诉我。 If it is, I'll explain in more detail. 如果是,我会更详细地解释。 No use continuing if I didn't understand your requirement properly 如果我不能正确理解您的要求,请继续使用

You can save information to ajax request in cookies or localStorage and make any worker that will send information. 您可以将信息保存到cookie或localStorage中的ajax请求中,并使任何将发送信息的工作人员。 Saving to cookies or localStorage is faster then ajax-request. 保存到cookie或localStorage比ajax-request更快。 You can do next: 你可以做下一个:

$(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);
});

So, when user click on link or send a form, data will be saved to storage and after user go to next page, this worker starts and send data to your server. 因此,当用户单击链接或发送表单时,数据将保存到存储中,在用户转到下一页后,此工作程序将启动并将数据发送到您的服务器。

The JavaScript is basically executed in single thread. JavaScript基本上是在单线程中执行的。 It is not possible to have your callback function executed and at the same time have an infinite loop waiting for a flag variable from it. 执行回调函数是不可能的,同时有一个无限循环等待它的标志变量。 The infinite loop will occupy the single execution thread and the callback will never be called. 无限循环将占用单个执行线程,并且永远不会调用回调。

Best approach is to cancel the default handler of your event and bubbling for it (basically return false if you are really building your tracking code with jQuery), and do the necessary actions (redirect page to the necessary address if a link was clicked or trigger other default actions), but this would take a lot of careful work to recreate all the possible combinations of actiona and callbacks. 最好的方法是取消事件的默认处理程序并为其冒泡(如果您真的使用jQuery构建跟踪代码,则基本上返回false),并执行必要的操作(如果单击链接或触发,则将页面重定向到必要的地址其他默认操作),但这需要花费大量精力来重新创建actiona和callback的所有可能组合。

Another approach is to: 1) Look for something specific to your code in the event data 2) If it is not present - make an AJAX call and in its callback re-trigger the same even on the same element, but this time with your specific bit added to the even data; 另一种方法是:1)在事件数据中查找特定于您的代码的内容2)如果它不存在 - 进行AJAX调用并在其回调中重新触发相同的元素,即使在同一元素上,特定位添加到偶数数据; after the AJAX call return false 3) If your specific bits are present in the data - simply do nothing, allowing the default event processing to take place. 在AJAX调用返回false之后3)如果您的特定位存在于数据中 - 根本不执行任何操作,允许进行默认事件处理。

The either approach may bite, however. 然而,这两种方法都可能会受到影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在重定向到单击的链接之前询问用户确认 - Asking user confirmation before redirect to a clicked link 在转到链接中的URL之前,如何将所有单击的链接发送到页面 - How to send all clicked links to a page before going to the URL in the link 如何在 Laravel Blade View PHP 中保存重定向页面信息 - How to save information about page on redirect in Laravel Blade View in PHP 单击链接并重定向时,如何添加活动类? - How can I add class active when a link clicked and redirect? 单击时将表格行重定向到链接 - Make a Table Row redirect to a link when it's clicked React Router:单击链接/按钮时如何重定向到不同的组件? - React Router: How to redirect to a different component when a link/button is clicked? 单击“是/否”用户界面按钮时,重定向到链接 - Having YES/NO user interface buttons redirect to a link when clicked 在发送请求之前编辑href链接 - Edit the href link before send the request 访问有关变量的信息,该变量之前已声明且已在函数中更改 - Accessing information about a variable that was declared before and changed in a function 使用PHP / JavaScript链接获取有关网站访问者的信息 - Using PHP/JavaScript link to get information about site visitor
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM