2013-07-18 45 views
0

在我的Rails应用程序中,使用jQuery滑块。在滑块停止事件中,有一个Ajax请求。如果用户不断滑动滑块,则有太多未决的Ajax请求,并且系统会挂起。我已经使用:如何停止所有活动或挂起的Ajax请求?

1:

function slide_stop(event, ui){ 
    $.xhrPool = []; 
    $.xhrPool.abortAll = function() { 
     $(this).each(function(idx, jqXHR) { 
      jqXHR.abort(); 
     }); 
     $.xhrPool.length = 0 
    }; 

    $.ajaxSetup({ 
     beforeSend: function(jqXHR) { 
      $.xhrPool.push(jqXHR); 
     }, 
     complete: function(jqXHR) { 
     var index = $.xhrPool.indexOf(jqXHR); 
     if (index > -1) { 
      $.xhrPool.splice(index, 1); 
     } 
     } 
    }); 
    $.xhrPool.abortAll(); 
    $('span#imgLoader').html('<img src="/assets/ajax-loader.gif">'); 
    $.ajax({ 
    type: 'get', 
    dataType: 'json', 
    url: 'some_url', 
    data: { is_ajax: true } 
    }).done(function(response){  
    $('span#imgLoader').empty(); 
    }); 
} 

Initialize slider, 
    $elt.slider({ 
     min:0, 
     max:100, 
     value:50, 
     slide: slide_range, 
     stop: slide_stop 
    }).each(function(){ 
    add_range_label($range_elt); 
    }); 

所有Ajax请求得到停止/在不修改状态。但是上次请求需要很长时间才能完成。没有结果再次挂相同的状态。

2:

var request = $.ajax(
{ 
    type: 'POST', 
    url: 'someurl', 
    success: function(result){} 
}); 

然后,

request.abort(); 

不工作。太多请求仍处于未决状态。 我不知道它有什么问题。

我试着用'jquery-throttle-debounce'。包含文件'jquery.ba-throttle-debounce.min.js' 应用jQuery.debounce停止滑块事件。

$("#slider").on("slidestop", $.debounce(240, slide_stop)); 

我试着减少时间延迟。但没有预期的结果。与上述情况相同。

+2

您是否考虑过首先减少请求?使用超时延迟请求,直到用户停止滑动几毫秒(例如300ms?)。 – nnnnnn

+2

要好得多才能发送请求,直到您检测到它们停止滑动为止。否则,控制台将充满中止警告。 –

回答

0

您可以使用插件,如http://archive.plugins.jquery.com/project/AjaxManager

另外,正如Javis所说,您最好在发送响应之前加入一个延迟,这样您就不会不必要地用请求重载服务器。而不是使用时间差或数组,我只会保留对最后创建的ajax请求的引用。每次制作新的请求时,您都会中止该请求。

// just putting these here for example, you would want to associate them with each instance of your slider control. 
var timeout, last_request; 

function slide_stop(event, ui){ 

    $('span#imgLoader').html('<img src="/assets/ajax-loader.gif">'); 
    // clear the timeout so a previous request won't be sent 
    clearTimeout(timeout) 
    // set the request to be sent in .5 seconds 
    timeout = setTimeout(send_request, 500); 
} 

function send_request(){ 
    // abort the last request if there is one 
    if(last_request){ 
    last_request.abort(); 
    } 
    last_request = $.ajax({ 
    type: 'get', 
    dataType: 'json', 
    url: 'some_url', 
    data: { is_ajax: true } 
    }).done(function(response){  
    $('span#imgLoader').empty(); 
    // set the last request to null so that you dont abort a completed request 
    //(this might not be necessary) 
    last_request = null; 
    }); 
} 
+0

对last_request进行了小改正,分配了$ .ajax。不工作,因为它中止了Ajax请求,但机器进入挂起状态。我没有理解它。 – kd12

+0

是啊......刚刚在这里试图找到我自己的“非插件”解决方案,以类似的概率。必须注意,您是中止连接并重新连接的解决方案并非完全证明。我一直在使用'if($ ajax)$ ajax.abort();'键入多年的东西,并且已经注意到,有时我仍然以双连接结束,但只有一个变量。无法找到其他连接存储位置的我的生活,但它是我的变量分配到的那个的完全重复。真的需要找到一个解决方案,因为这是在Chrome上吃掉了套接字... – SpYk3HH

0

尝试抑制这些请求,因此请求服务器的很多请求可能会导致服务器端的性能问题,因为请记住每个ajax调用都是apache(或任何web服务器)请求,这会花费内存和cpu。请记住,过多的请求可能会导致DDoS。

请记住,作为一个用户,我可以像我喜欢的那样开始使用滑块进行播放,从而导致大量的请求。

您应该添加类似:

var requests = []; 
var lastCall = (+new Date()); // parenthesis just in case of minify 
var timeDiff = 1000; 

function sliderStopCallback() { // this will be called each time the slider stop sliding 
    if(timeDiff < 400) { 
     return; 
    } 

    abortAll(); 

    requests.push($.ajax({ 
          type: 'POST', 
          url: 'someurl', 
          success: function(result){} 
       })); 
} 

function sliderStartCallback() { // this will be call each time the user start to slide 
    timeDiff = (+new Date()) - lastCall; 
    lastCall = (+new Date()); 
} 

function abortAll() { 
    var l = requests.length; 
    while(l--) { 
     requests[l].abort && requests[l].abort(); // the if is for the first case mostly, where array is still empty, so no abort method exists. 
    } 
} 

这样一来,每个请求将在400毫秒内发送至少,防止通话每2秒。

应该工作,但请注意,我还没有测试过,所以如果你要尝试它,请记住,这是一个普遍的想法,而不是一个精确的解决方案。

祝你好运。

0

正如评论中所说,最好不要发送请求,直到slideStop事件。通过这种方式,每次值被更改时都不会发送请求,因此服务器负载的问题更少。

function ajaxrequest(){ 
    $.ajax(....); 
} 

$("#slider").on("slideStop", function() { 

    ajaxrequest(); 

});