【问题标题】:Avoid identical client ajax request on refresh刷新时避免相同的客户端 ajax 请求
【发布时间】:2018-03-31 06:19:26
【问题描述】:

我想测试 ajax 请求是否相同,以便可以中止或采取其他一些警报操作?

实际上,客户端可以通过一些表单元素更改请求,然后点击刷新按钮。

我在捕获相同的请求方面尝试不佳。需要保留定时器刷新功能。

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>

<script type="text/javascript">

    var current_request_id = 0;
    var currentRequest = null;
    var lastSuccessfulRequest = null;

    function refreshTable() {
        $('#select').html('Loading');
        window.clearTimeout(timer);

        //MY CATCH FOR DUPLICATE REQUEST NEEDS WORK
        if (lastSuccessfulRequest == currentRequest)
        {
            //currentRequest.abort();
            alert('Duplicate query submitted. Please update query before resubmission.');
        }

        var data = {   
            "hide_blanks": $("#hide_blanks").prop('checked'),
            "hide_disabled": $("#hide_disabled").prop('checked'),
        };

        json_data = JSON.stringify(data);

        current_request_id++;
        currentRequest = $.ajax({
            url: "/calendar_table",
            method: "POST",
            data: {'data': json_data},
            request_id: current_request_id,
            beforeSend : function(){
                if(currentRequest != null) {
                    currentRequest.abort();
                }
            },
            success: function(response) {
                if (this.request_id == current_request_id) {
                    $("#job_table").html(response);
                    $("#error_panel").hide();
                    setFixedTableHeader();
                }
            },
            error: function(xhr) {
                if (this.request_id == current_request_id) {
                    $("#error_panel").show().html("Error " + xhr.status + ": " + xhr.statusText + "<br/>" + xhr.responseText.replace(/(?:\r\n|\r|\n)/g, "<br/>"));
                }
            },
            complete: function(response) {
                if (this.request_id == current_request_id) {
                    $("#select").html("Refresh");
                    window.clearTimeout(timer);
                    stopRefreshTable();
                    window.refreshTableTimer = window.setTimeout(refreshTable, 10000);

                    lastSuccessfulRequest = currentRequest;
                }
            }
        });
    }




    //TIMER STUFF TO refreshTable()
    //THIS SECTION WORKS FINE
    var startDate = new Date();
    var endDate = new Date();
    var timer = new Date();
    function startRefreshTable() {
        if(!window.refreshTableTimer) {
            window.refreshTableTimer = window.setTimeout(refreshTable, 0);
        }
    }
    function stopRefreshTable() {
        if(window.refreshTableTimer) {
            self.clearTimeout(window.refreshTableTimer);
        }
        window.refreshTableTimer = null;
    }
    function resetActive(){ 
        clearTimeout(activityTimeout);
        activityTimeout = setTimeout(inActive, 300000);
        startRefreshTable();
    }

    function inActive(){
        stopRefreshTable();
    }
    var activityTimeout = setTimeout(inActive, 300000);
    $(document).bind('mousemove click keypress', function(){resetActive()});

</script>


<input type="checkbox" name="hide_disabled" id="hide_disabled" onchange="refreshTable()">Hide disabled task<br>
<br><br>
<button id="select" type="button" onclick="refreshTable();">Refresh</button>

【问题讨论】:

  • " 是相同的"...与什么相同,确切地说?之前的要求?之前有什么要求吗?还有什么?在什么意义上相同?来自同一用户?完全相同的参数?相同的标题?请澄清您的确切要求。你现在这样做的方式很幼稚。 $.ajax 返回一个 Deferred 对象,您无法以任何有意义的方式将其与另一个对象进行真正的“平等”比较,并且也不会告诉您有关请求内容的任何信息 - 它旨在为您添加回调以便处理响应。一旦你澄清了你的意思,我们可以找到更好的方法来做到这一点
  • 另外附注:jQuery 的 .bind 在 jQuery 1.7 中已被 .on 取代,现在已完全弃用。应该没有理由继续使用它,或者更糟的是,将它用于新代码。 api.jquery.com/bind
  • 当然有一种方法可以在不发布一百行代码的情况下说明您的观点。阅读并关注minimal reproducible example

标签: javascript jquery ajax duplicates


【解决方案1】:

我会使用.ajaxSend.ajaxSuccess 全局处理程序的强大功能。

我们将使用 ajaxSuccess 来存储一个缓存,ajaxSend 将首先尝试读取它,如果成功将立即触发请求的成功处理程序,并中止即将完成的请求。否则就顺其自然吧……

var ajax_cache = {};
function cache_key(settings){
    //Produce a unique key from settings object;
    return settings.url+'///'+JSON.encode(settings.data);
}
$(document).ajaxSuccess(function(event,xhr,settings,data){
    ajax_cache[cache_key(settings)] = {data:data};
    // Store other useful properties like current timestamp to be able to prune old cache maybe?
});
$(document.ajaxSend(function(event,xhr,settings){
    if(ajax_cache[cache_key(settings)]){
        //Add checks for cache age maybe? 
        //Add check for nocache setting to be able to override it?
        xhr.abort();
        settings.success(ajax_cache[cache_key(settings)].data);
    }
});

我在这里展示的是一种非常幼稚但实用的方法来解决您的问题。这样做的好处是可以为您可能拥有的每个 ajax 调用工作,而无需更改它们。您需要在此基础上考虑故障,并确保来自缓存命中的请求中止不会被分派到中止处理程序。

【讨论】:

    【解决方案2】:

    这里的一个有效选项是JSON.Stringify() 对象并比较字符串。如果对象相同,则生成的序列化字符串应该相同。

    如果您直接从响应中使用已经 JSON 化的字符串,则可能存在导致细微差异的边缘情况,因此您必须通过测试仔细检查。

    此外,如果您想弄清楚如何在页面加载时将其持久化,请使用 localStorage.setItem("lastSuccessfulRequest", lastSuccessfulRequest)localStorage.getItem("lastSuccessfulRequest")。 (如果没有,请告诉我,我会删除它。)

    【讨论】:

      猜你喜欢
      • 2021-04-13
      • 2015-03-02
      • 2014-02-03
      • 2019-06-21
      • 2014-06-20
      • 1970-01-01
      • 1970-01-01
      • 2019-05-06
      • 1970-01-01
      相关资源
      最近更新 更多