DataTables - 当一个新请求开始时终止 ajax 请求

Posted

技术标签:

【中文标题】DataTables - 当一个新请求开始时终止 ajax 请求【英文标题】:DataTables - kill ajax requests when a new one has started 【发布时间】:2017-12-06 20:25:43 【问题描述】:

我在服务器端模式下使用 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,并且接受的答案似乎对我不起作用。

【问题讨论】:

你不能。它已经在服务器脚本上处理。 我了解到服务器正在处理脚本getData.php。但是可以停止 ajax 请求(例如 jquery 中的.abort())。所以我想要做的是,如果已经向getData.php 提出了两个请求,它会杀死第一个请求,然后继续下一个请求。这样就没有脚本排队。该应用程序适用于每个按键,因此如果用户输入 4 个字符进行搜索,则不需要执行前 3 个搜索 - 它们可以在服务器处理它们之前被杀死。我知道这是可能的,因为它在我发布的链接上,只是针对旧数据表版本。 你可以设置一个标志,比如processing,然后如果processing为真,则避免执行ajax请求,当ajax成功时,设置processing为假。 您还可以插入延迟以执行搜索。劫持搜索输入事件并仅在 500 毫秒间隔后触发搜索。这个问题已经被问过好几次了。我知道如果你用谷歌搜索一下就会有答案。 好的,谢谢。我认为关于旗帜的部分可能是我所缺少的,并且似乎是个好主意。 【参考方案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。是的,我确实使用了我在那里给出的答案中的代码,但那是拆解代码,它是测试套件的一部分,而不是应用程序代码。)从理论上讲,这似乎是一件好事做。毕竟,新查询会使旧查询过时,那么为什么不放弃旧查询并节省一些工作呢?正确的?在实践中,收益将是适度的,因为:

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

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

您可能会节省一些重绘时间,但这不是我担心的事情,直到它真正成为一个问题。

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

【讨论】:

优秀。有很多事情我没有考虑过——以前甚至从未听说过去抖函数。将对此进行更多研究。非常感谢。 您能否确认我是否可以删除我添加的一些代码以停止 ajax 请求排队,这些代码是 if (settings.jqXHR) settings.jqXHR.abort(); - 这是放在 .on( 'preXhr.dt', function (e, settings, data) 中的 我的想法太长了,无法发表评论,所以我编辑了我的答案。

以上是关于DataTables - 当一个新请求开始时终止 ajax 请求的主要内容,如果未能解决你的问题,请参考以下文章

ioS Swift新用户无法登录,直到应用程序终止并启动

当响应时间超过 requestReadTimeoutSeconds 时,KTor 将终止 GET 请求

当应用程序进程被终止时,请勿打开上一个活动

Elastic Beanstalk 滚动环境配置更新

带有 ajax 的 DataTables 1.10.6,为第 0 行请求未知参数 0

当应用程序处于后台或终止状态时,如何找到用户位置?