DataTables-启动一个新的Ajax请求 [英] DataTables - kill ajax requests when a new one has started

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

问题描述

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

I'm using DataTables 1.10.15 in Server Side mode.

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

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

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

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

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

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

无论何时发出新的ajax请求,我如何都可以取消它们,以免它们以这种方式排队?我已阅读我该如何停止DataTables实例已启动的所有当前正在进行的Ajax查询?但是该解决方案是针对较旧版本的DataTables的,并且似乎无法接受这个答案.

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.

推荐答案

如果您使用的是DataTable默认提供的搜索字段,则需要使用,因此您不能在用例中使用此选项.

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.

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

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'm a little teapot",我只会在控制台上看到一次"drawing".

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>

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

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. 以人类与您的GUI交互的速度,很有可能在发出abort()调用时,Ajax请求将已经在网络上发出. (实际上,我进行了一些手动测试,确实,我的速度还不够快,无法阻止浏览器将请求发送出去.)因此,即使您中止请求,服务器也将收到请求.

  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.

此外,abort()并不意味着通知服务器该请求已被取消.因此,您将不会在服务器上保存工作.请查看此问题以了解相关问题. (在页面上搜索服务器"将使您直接在人们谈论服务器是否被通知的问题以及如果您需要通知服务器已取消请求的情况下该怎么做.)

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.

另一方面,中止这样的请求可能会导致其他问题.为了查看会发生什么,我修改了我的一个应用程序以中止旧的请求,整个事件立即遭到轰炸.中止请求在我设置DataTables的方式中不能很好地发挥作用.我不知道到底是什么引起了问题.也许我只是在使用正确的设置来使其蓬勃发展.或者我使用的插件不喜欢中止的请求.无论如何,中止请求都可能导致问题.

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天全站免登陆