DataTables - 在新的请求启动时终止ajax请求

时间:2017-07-03 14:11:11

标签: jquery ajax datatables

我在服务器端模式下使用DataTables 1.10.15。

我通过ajax将表单的内容传递给PHP脚本,以便搜索数据库:

 var myTable = $('#myTable').DataTable( {
    "processing": false,
    "serverSide": true,
    "searching": false,
    "ajax": { 
        "url" : "/getData.php",
        "data" : function ( d ) {
            // Search input data
            d.field1 = $('#field1').val(),
            d.field2 = $('#field2').val(),
            d.field3 = $('#field3').val()
        },
        "method" : "POST",
    }
 });

在向/getData.php发送ajax请求之前,我还有一些其他js检查输入到字段中的至少3个字符。

这意味着 - 在输入3个字符后 - 每次按键时都会发出ajax请求,因此可能会有一个ajax请求队列。

$('#primarySearch input[type="text"]').on({
    "keyup": function(e) {
      // Ignore tab key.
      if (e.which != 9) {
        processPrimarySearch.call(this);

      }
    }
});


/* Handle Primary Search */
function processPrimarySearch() {
    var obj = $(this),
        search_id = obj.attr('id'), // e.g. #field1
        search_value = obj.val(); // e.g. '123-456'

    /* Wait until at least 3 characters have been entered, or user has cleared the input */
    if (search_value.length >= 3 || (!search_value) ) {
        myTable.draw();
    }   
}

如果制作新的ajax请求,我怎么能杀掉之前的ajax请求,这样它们就不会以这种方式排队?我已阅读How can I stop all the currently ongoing Ajax queries that DataTables instance have started?,但解决方案适用于旧版本的DataTables,并且接受的答案对我来说似乎不起作用。

1 个答案:

答案 0 :(得分:1)

如果您使用DataTable默认提供的搜索字段,则您需要使用searchDelay option。默认情况下,使用服务器端处理时,它设置为400毫秒。但是,您有"searching": false,因此您不能将此选项用于您的用例。

您提供自己的自定义input元素来执行搜索。这是DataTables的完全有效使用。 但是,您应该做的不是在创建请求后中止请求,而是首先阻止创建无关请求。您应该做的是撤消对myTable.draw()的调用。在示例中下面我正在使用Lodash的debounce。如果需要,您可以使用其他库中的实现。在下面的示例中,我还修改了事件处理,以检查输入字段值是否在击键之间实际发生了更改。您正在检查选项卡,但这只是冰山一角。使用箭头键也会生成keyup个事件。仅按下并释放shift键的事件将生成keyup。下面的代码通过检查自上次笔划以来字段的值是否已更改来处理所有这些情况,如果没有更改则忽略该事件。

我输入的速度足够快,如果我在下面的示例中显示的字段中键入“我是一个小茶壶”,我只会在控制台上看到“绘图”一次。

// We create a new function that will debounce calls to the draw() function.
var debouncedDraw = _.debounce(function() {
  // myTable.draw();
  console.log("drawing");
}, 500);


var prev_value = undefined;

/* Handle Primary Search */
function processPrimarySearch() {
  var obj = $(this),
    search_id = obj.attr('id'), // e.g. #field1
    search_value = obj.val(); // e.g. '123-456'

  // There's been no change to the field, ignore.
  if (prev_value === search_value) {
    return;
  }
  prev_value = search_value;

  /* Wait until at least 3 characters have been entered, or user has cleared the input */
  if (search_value.length >= 3 || (!search_value)) {
    debouncedDraw();
  }
}

$('#primarySearch input[type="text"]').on("keyup", processPrimarySearch);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="primarySearch">
  <input type="text">
</div>

您在评论中询问是否应该保留您的代码,以便在DataTables启动新查询时中止DataTables发起的任何先前的Ajax查询。我会删除它。我从来没有在我的应用程序中依赖这样的代码。 (你提到my question。是的,我确实使用了我在那里给出的答案中的代码,但这是代码,它是测试套件的一部分,而不是应用程序代码。)从理论上讲,这似乎是一个好的要做的事。毕竟,一个新的查询使旧的查询过时,为什么不放弃旧的查询并保存一些工作呢?对?在实践中,收益将是适度的,因为:

  1. 在人与GUI交互的速度下,有可能在发出abort()调用时,Ajax请求已经在网络上发送出去了。 (我实际上运行了一些手动测试,实际上,我从来没有足够快到阻止浏览器发出请求。)这意味着即使你中止它,服务器也会收到它。

  2. 此外,abort()并不意味着通知服务器请求已被取消。因此,您不会在服务器上保存工作。查看问题的this question。 (在页面上搜索“服务器”会使人们谈论服务器是否得到通知的问题,以及如果需要通知服务器请求已被取消,该怎么办。)

    < / LI>

    你可能会节省一些重绘时间,但这不是我担心的问题,直到实际出现问题为止。

    另一方面,中止像这样的请求可能会导致其他问题。为了看到会发生什么,我修改了我的一个应用程序以中止旧请求,整个事情立即遭到轰炸。中止请求与我设置DataTables的方式不符。我不知道究竟是什么导致了这个问题。也许我正在使用正确的设置让它变得繁荣。或者我使用的是不喜欢中止请求的插件。无论如何,中止请求可能会导致问题。