DataTables - 当一个新的请求开始时终止 ajax 请求 [英] DataTables - kill ajax requests when a new one has started

查看:18
本文介绍了DataTables - 当一个新的请求开始时终止 ajax 请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

 var myTable = $('#myTable').DataTable( {处理":假,服务器端":真,搜索":假,阿贾克斯":{"url" : "/getData.php",数据":函数(d){//搜索输入数据d.field1 = $('#field1').val(),d.field2 = $('#field2').val(),d.field3 = $('#field3').val()},方法":POST",}});

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

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

$('#primarySearch input[type="text"]').on({keyup":函数(e){//忽略tab键.如果 (e.which != 9) {processPrimarySearch.call(this);}}});/* 处理主要搜索 */函数 processPrimarySearch() {var obj = $(this),search_id = obj.attr('id'),//例如#field1search_value = obj.val();//例如'123-456'/* 等待输入至少 3 个字符,或者用户已清除输入 */if (search_value.length >= 3 || (!search_value) ) {myTable.draw();}}

如何在发出新请求时终止之前的 ajax 请求,以免它们以这种方式排队?我读过 如何停止 DataTables 实例已启动的所有当前正在进行的 Ajax 查询? 但该解决方案适用于较旧版本的 DataTables,并且已接受的答案似乎对我不起作用.

解决方案

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

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

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

//我们创建了一个新函数,用于消除对 draw() 函数的调用.var debouncedDraw = _.debounce(function() {//myTable.draw();console.log("绘图");}, 500);var prev_value = 未定义;/* 处理主要搜索 */函数 processPrimarySearch() {var obj = $(this),search_id = obj.attr('id'),//例如#field1search_value = obj.val();//例如'123-456'//字段没有变化,忽略.if (prev_value === search_value) {返回;}prev_value = search_value;/* 等待输入至少 3 个字符,或者用户已清除输入 */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"><输入类型=文本">

<小时>

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

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

  2. 此外,abort() 并不意味着通知服务器请求已被取消.因此,您不会节省服务器部分的工作.查看这个问题以了解问题.(在页面上搜索服务器"将带您到人们谈论是否通知服务器的问题,以及如果您需要通知服务器请求已被取消该怎么办.)

您可能会节省一些重绘时间,但这不是我担心的事情,直到它确实是一个问题.

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

I'm using DataTables 1.10.15 in Server Side mode.

I'm passing the contents of a form to a PHP script via ajax in order for it to search a database:

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

I have some other js which checks for at least 3 characters entered into a field before firing the ajax request to /getData.php.

This means - after 3 characters have been entered - that an ajax request is made each time a key is pressed, so there can be a queue of ajax requests.

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

How can I kill off the previous ajax requests whenever a new one is made, so that they don't queue in this way? I've read How can I stop all the currently ongoing Ajax queries that DataTables instance have started? but the solution is for an older version of DataTables and the accepted answer doesn't seem to work for me.

解决方案

If you were using the search field that DataTable offers by default, you'd want to use the searchDelay option. By default it is set to 400ms when you use server-side processing. However, you have "searching": false, therefore you cannot use this option for your use-case.

You provide your own custom input element to perform searches. This is a perfectly valid use of DataTables. However, what you should do is not abort requests after they are created but prevent the creation of extraneous requests in the first place. What you should do is debounce your calls to myTable.draw() In the example below I'm using Lodash's debounce. You could use an implementation from another library if you want. In the following example, I've also modified the event handling to check whether the input field value has actually changed between keystrokes. You were checking for tabs but that's only the tip of the iceberg. Using arrow keys will also generate keyup events. Event just pressing and releasing the shift key will generate a keyup. The code below takes care of all those situations by checking whether the value of the field has changed since the last stroke and just ignore the event if there has been no change.

I type fast enough that if I type "I'm a little teapot" in the field presented in the example below I'm seeing "drawing" on the console only once.

// 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>


You asked in a comment if you should keep the code you had that aborts any previous Ajax query launched by DataTables when DataTables launches a new query. I would remove it. I've never relied on such code ever in my applications. (You mentioned my question. Yes, I do use the code in the answer I gave there but that's tear down code which is part of a test suite, not application code.) In theory it would seem like it is a good thing to do. After all, a new query makes the old ones obsolete so why not ditch the old queries and save some work? Right? In practice, the gains would be modest because:

  1. At the speed humans interact with your GUI, chances are that by the time an abort() call is issued, the Ajax request will already have been sent out on the network. (I actually ran some manual tests, and indeed, I was never fast enough to prevent the browser from sending the request out.) So it means that the server will receive it even if you abort it.

  2. Furthermore, abort() is not meant to notify the server that the request has been cancelled. So you won't save work on the part of your server. Look at this question for the issues. (Searching for "server" on the page will bring you right where people talk about the issue of whether the server is notified, and what to do if you need to notify the server that a request has been cancelled.)

You may be saving some redrawing time but that's not something I'd worry about until it is actually a problem.

On the other hand, aborting requests like this may cause other problems. For the sake of seeing what would happen, I modified one of my applications to abort old requests, and the whole thing immediately bombed. Aborting requests did not play well with the way I've set up DataTables. I don't know what exactly is causing the problem. Maybe I'm using just the right settings to get it to go boom. Or I'm using a plugin that does not like aborted requests. At any rate, aborting requests can cause problems.

这篇关于DataTables - 当一个新的请求开始时终止 ajax 请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆