2

我有一段有点大的 javascript/ajax 代码,我想看看是否有可能在不使用任何功能的情况下让它更有效地运行。

我的问题是我得到一个名为“getlastupdate.php”的页面,它只有 14 个数字,这些数字是上次更新数据库表的日期和时间。

格式为:

  • 年-月-日-HH-mm:ss

这是一个例子:20130724082105

我取出了':.-',因为我们不需要它。

我的 javascript 代码将此与另一个 ajax GET 进行比较,后者重复从“getlastupdate.php”获取当前日期/时间。如果它发现这两个值不相同,它会触发另一个 GET 来获取行信息。

它获取更新的行信息并将其显示在浏览器中。最后它获取整个更新的表并将其放回表中(tablesorter)。

一切似乎都很好,但是当脚本添加新表信息并删除旧表信息时,我注意到了一些滞后?或者至少我认为这是 LAG 的主要原因。

这是代码:

<link type="text/css" rel="stylesheet" href="tablesorter/qtip/jquery.qtip.min.css" />
<script type="text/javascript" src="tablesorter/jquery-1.10.2.min.js"></script> 
<!-- blue theme stylesheet -->
<link rel="stylesheet" href="tablesorter/final/theme.blue.css">
<!-- tablesorter plugin -->
<script src="tablesorter/final/jquery.tablesorter.js"></script>
<!-- tablesorter widget file - loaded after the plugin -->
<script src="tablesorter/final/jquery.tablesorter.widgets.js"></script>


<!-- START: toastmessage Notify -->
    <link type="text/css" href="tablesorter/final/toastmessage/jquery.toastmessage-min.css" rel="stylesheet"/>
    <script type="text/javascript" src="tablesorter/final/toastmessage/jquery.toastmessage-min.js"></script>
<!-- END: toastmessage Notify -->


<script type="text/javascript" src="tablesorter/qtip/jquery.qtip.min.js"></script>


<script type="text/javascript">
var comper;
function checkComper() {
var SvInfo;

  var onResponse = function(comperNow) {  // comperNow is the latest date/time var
    //check if comper has been set / first time method is called
    if (comper === undefined) {
      comper = comperNow;
      return;
    }

    if (comper !== comperNow) {


var Vinfoo;
$.get("getlastupdate2.php", function(primaryAddType){
//   alert("Data: " + primaryAddType);
   Vinfoo = primaryAddType;


// show a message to the visitor ----> 
//alert(Vinfoo);
  $().toastmessage('showNoticeToast', Vinfoo);


 });
$('#append').trigger('click'); // UPDATE THE TABLE BUT IT TAKES 3-4 SEC. AND I NEED IT TO SPEED UP!

// and update comper to show the date/time from comperNow
comper = comperNow;
}
};
$.get('getlastupdate.php', onResponse);

}
var tid = setInterval(checkComper, 2000); // repeat myself

$(function() {

$('[title!=""]').qtip({}); // A bit better. Grab elements with a title attribute that isn't blank. <-- CUSTOM TOOLTIP

var $table = $("table.tablesorter");
$("#append").click(function(e) { 
e.preventDefault();
$.get('updatetable.php', function(data) 
{
$table
.find('tbody')
.html('')
.append(data);
$table.trigger("update", [true]);

$('[title!=""]').qtip({}); // A bit better. Grab elements with a title attribute that isn't blank. <-- CUSTOM TOOLTIP

});
});

  // call the tablesorter plugin
$("table.tablesorter").tablesorter({
    theme: 'blue',

    // hidden filter input/selects will resize the columns, so try to minimize the change
    widthFixed : true,

    //sortList: [[2,0],[1,0]],

    // initialize zebra striping and filter widgets
    widgets: ["saveSort", "zebra", "filter"],

//  headers: {  },

    widgetOptions : {

      // If there are child rows in the table (rows with class name from "cssChildRow" option)
      // and this option is true and a match is found anywhere in the child row, then it will make that row
      // visible; default is false
      filter_childRows : false, 

      // if true, a filter will be added to the top of each table column;
      // disabled by using -> headers: { 1: { filter: false } } OR add class="filter-false"
      // if you set this to false, make sure you perform a search using the second method below
      filter_columnFilters : true,

      // css class applied to the table row containing the filters & the inputs within that row
      filter_cssFilter : 'tablesorter-filter',

      // class added to filtered rows (rows that are not showing); needed by pager plugin
      filter_filteredRow   : 'filtered',

      // add custom filter elements to the filter row
      // see the filter formatter demos for more specifics
      filter_formatter : null,

      // add custom filter functions using this option
      // see the filter widget custom demo for more specifics on how to use this option
      filter_functions : null,

      // if true, filters are collapsed initially, but can be revealed by hovering over the grey bar immediately
      // below the header row. Additionally, tabbing through the document will open the filter row when an input gets focus
      filter_hideFilters : false, // true, (see note in the options section above)

      // Set this option to false to make the searches case sensitive
      filter_ignoreCase : true,

      // if true, search column content while the user types (with a delay)
      filter_liveSearch : true,

      // jQuery selector string of an element used to reset the filters
      filter_reset : 'button.reset',

      // Delay in milliseconds before the filter widget starts searching; This option prevents searching for
      // every character while typing and should make searching large tables faster.
      filter_searchDelay : 300,

      // if true, server-side filtering should be performed because client-side filtering will be disabled, but
      // the ui and events will still be used.
      filter_serversideFiltering: false,

      // Set this option to true to use the filter to find text from the start of the column
      // So typing in "a" will find "albert" but not "frank", both have a's; default is false
      filter_startsWith : false,

      // Filter using parsed content for ALL columns
      // be careful on using this on date columns as the date is parsed and stored as time in seconds
      filter_useParsedData : false

    }

  });

  // External search
  // buttons set up like this:
  // <button type="button" class="search" data-filter-column="4" data-filter-text="2?%">Saved Search</button>
  $('button.search').click(function(){
    /*** first method *** data-filter-column="1" data-filter-text="!son"
      add search value to Discount column (zero based index) input */
    var filters = [],
      col = $(this).data('filter-column'), // zero-based index
      txt = $(this).data('filter-text'); // text to add to filter

    filters[col] = txt;
    // using "table.hasFilters" here to make sure we aren't targetting a sticky header
    $.tablesorter.setFilters( $('table.hasFilters'), filters, true ); // new v2.9

    /** old method (prior to tablsorter v2.9 ***
    var filters = $('table.tablesorter').find('input.tablesorter-filter');
    filters.val(''); // clear all filters
    filters.eq(col).val(txt).trigger('search', false);
    ******/

    /*** second method ***
      this method bypasses the filter inputs, so the "filter_columnFilters"
      option can be set to false (no column filters showing)
    ******/
    /*
    var columns = [];
    columns[5] = '2?%'; // or define the array this way [ '', '', '', '', '', '2?%' ]
    $('table').trigger('search', [ columns ]);
    */

    return false;
  });

});
</script>

如果我注释掉这一行,我找到了 LAG 的来源:

$('#append').trigger('click'); // UPDATE THE TABLE BUT IT TAKES 3-4 SEC. AND I NEED IT TO SPEED UP! it will speed everything up but how do I get it to speed up or even slow down so that it doesn't lock up the current page.

如果我注释掉这个,还可以加快加载速度:

    var $table = $("table.tablesorter");
    $("#append").click(function(e) { 
    e.preventDefault();
    $.get('updatetable.php', function(data) 
    {
    $table
    .find('tbody')
    .html('')
    .append(data);
    $table.trigger("update", [true]);

// ******** +++++++++++ **************    

    $('[title!=""]').qtip({}); // <-- CUSTOM TOOLTIP THIS SLOWS DOWN THE LOADING ALSO!!!!!

// ******** +++++++++++ **************    
    });
    });

@Abudoul Sy,这是我现在拥有的:

<script type="text/javascript">
// I should be put at the top of the file (not in an Ajax Loop)
var compileHTML = function (html) {
        var div = document.createElement("div");
        div.innerHTML = html;
        var fragment = document.createDocumentFragment();
        while ( div.firstChild ) {
            fragment.appendChild( div.firstChild );
        }
        return fragment
    };

var comper;
function checkComper() {
var SvInfo;

  var onResponse = function(comperNow) {  // comperNow is the latest date/time var
    //check if comper has been set / first time method is called
    if (comper === undefined) {
      comper = comperNow;
      return;
    }

    if (comper !== comperNow) {


var Vinfoo;
$.get("getlastupdate2.php", function(primaryAddType){
//   alert("Data: " + primaryAddType);
   Vinfoo = primaryAddType;


// show a message to the visitor ----> 
//alert(Vinfoo);
  $().toastmessage('showNoticeToast', Vinfoo);


 });
$('#append').trigger('click'); // UPDATE THE TABLE BUT IT TAKES 3-4 SEC. AND I NEED IT TO SPEED UP!

// and update comper to show the date/time from comperNow
comper = comperNow;
}
};
$.get('getlastupdate.php', onResponse);

}
var tid = setInterval(checkComper, 2000); // repeat myself

$(function() {

        $(document).ready(function()
        {
        $('[title!=""]').qtip({}); // A bit better. Grab elements with a title attribute that isn't blank. <-- CUSTOM TOOLTIP
        })

var $table = $("table.tablesorter");
//Keeping a reference variable to 
var $tableContents = $table.find('tbody');


$("#append").click(function(e) { 
e.preventDefault();
$.get('updatetable.php', function(data) 
{
$table

 //When ajax is done
var compiledHtml = window.compileHTML(data); 
 $tableContents.html(compiledHTML);
 $table.trigger("update", [true]);


        $(document).ready(function()
        {
        $('[title!=""]').qtip({}); // A bit better. Grab elements with a title attribute that isn't blank. <-- CUSTOM TOOLTIP
        })

});
});

  // call the tablesorter plugin
$("table.tablesorter").tablesorter({
    theme: 'blue',

    // hidden filter input/selects will resize the columns, so try to minimize the change
    widthFixed : true,

    //sortList: [[2,0],[1,0]],

    // initialize zebra striping and filter widgets
    widgets: ["saveSort", "zebra", "filter"],

    headers: { 8: { sorter: false, filter: false } },

    widgetOptions : {

      // If there are child rows in the table (rows with class name from "cssChildRow" option)
      // and this option is true and a match is found anywhere in the child row, then it will make that row
      // visible; default is false
      filter_childRows : false, 

      // if true, a filter will be added to the top of each table column;
      // disabled by using -> headers: { 1: { filter: false } } OR add class="filter-false"
      // if you set this to false, make sure you perform a search using the second method below
      filter_columnFilters : true,

      // css class applied to the table row containing the filters & the inputs within that row
      filter_cssFilter : 'tablesorter-filter',

      // class added to filtered rows (rows that are not showing); needed by pager plugin
      filter_filteredRow   : 'filtered',

      // add custom filter elements to the filter row
      // see the filter formatter demos for more specifics
      filter_formatter : null,

      // add custom filter functions using this option
      // see the filter widget custom demo for more specifics on how to use this option
      filter_functions : null,

      // if true, filters are collapsed initially, but can be revealed by hovering over the grey bar immediately
      // below the header row. Additionally, tabbing through the document will open the filter row when an input gets focus
      filter_hideFilters : false, // true, (see note in the options section above)

      // Set this option to false to make the searches case sensitive
      filter_ignoreCase : true,

      // if true, search column content while the user types (with a delay)
      filter_liveSearch : true,

      // jQuery selector string of an element used to reset the filters
      filter_reset : 'button.reset',

      // Delay in milliseconds before the filter widget starts searching; This option prevents searching for
      // every character while typing and should make searching large tables faster.
      filter_searchDelay : 300,

      // if true, server-side filtering should be performed because client-side filtering will be disabled, but
      // the ui and events will still be used.
      filter_serversideFiltering: false,

      // Set this option to true to use the filter to find text from the start of the column
      // So typing in "a" will find "albert" but not "frank", both have a's; default is false
      filter_startsWith : false,

      // Filter using parsed content for ALL columns
      // be careful on using this on date columns as the date is parsed and stored as time in seconds
      filter_useParsedData : false

    }

  });

  // External search
  // buttons set up like this:
  // <button type="button" class="search" data-filter-column="4" data-filter-text="2?%">Saved Search</button>
  $('button.search').click(function(){
    /*** first method *** data-filter-column="1" data-filter-text="!son"
      add search value to Discount column (zero based index) input */
    var filters = [],
      col = $(this).data('filter-column'), // zero-based index
      txt = $(this).data('filter-text'); // text to add to filter

    filters[col] = txt;
    // using "table.hasFilters" here to make sure we aren't targetting a sticky header
    $.tablesorter.setFilters( $('table.hasFilters'), filters, true ); // new v2.9

    /** old method (prior to tablsorter v2.9 ***
    var filters = $('table.tablesorter').find('input.tablesorter-filter');
    filters.val(''); // clear all filters
    filters.eq(col).val(txt).trigger('search', false);
    ******/

    /*** second method ***
      this method bypasses the filter inputs, so the "filter_columnFilters"
      option can be set to false (no column filters showing)
    ******/
    /*
    var columns = [];
    columns[5] = '2?%'; // or define the array this way [ '', '', '', '', '', '2?%' ]
    $('table').trigger('search', [ columns ]);
    */

    return false;
  });

});
</script>
4

3 回答 3

4

查看您的代码:
每次执行 Ajax 请求时,您都在执行以下操作:

$table
.find('tbody')
.html('')
.append(data);
$table.trigger("update", [true]);

解释它的作用:

  1. 你调用$.find一个 html 标签(慢)
  2. 您删除表格的内容(导致浏览器将像素重新绘制为白色)
  3. 您要求浏览器的 DOM 解析整个 html 表,从而导致多次布局重新处理和重新绘制(非常糟糕)
  4. 在桌子上调用触发器(好的)

我认为仅仅通过更好地处理你的数据可以根据你的表的大小无数次地加速你的过程。考虑一下:

// I should be put at the top of the file (not in an Ajax Loop)
window.compileHTML = function (html) {
    var div = document.createElement("div");
    div.innerHTML = html;
    var fragment = document.createDocumentFragment();
    while ( div.firstChild ) {
        fragment.appendChild( div.firstChild );
    }
    return fragment
};
//Keeping a reference variable to 
var $tableContents = $table.find('tbody')

//When ajax is done
var compiledHtml = window.compileHTML(data);
$tableContents.html(compiledHtml);
$table.trigger("update", [true]);

编辑:如果compileHTML不起作用。做几乎相同的事情(但不编译)的一个好方法是:

//put just after $table declaration
var $tableContents = $table.find('tbody')

//When ajax is done
var $html = $('<tbody/>').html(data);
$tableContents.replaceWith($html)
$table.trigger("update", [true]);

编辑:

我所做的是创建一个文档片段(在 DOM 之外),让 html 处理通过compileHTML在当前页面上没有任何影响。当一切都完成后。仅将创建的新 dom 树的根附加到 DOM,只导致一次重绘:“与单元格和行一样多”将使您的浏览器看起来更稳定。

可选(不完全):您的代码可能存在更多陷阱,但很难调查性能。我建议在Chrome/Firebug上进行时间线检查-> 打开控制台(F12Alt++ shifti按“时间线”选项卡。
按 ( ctrl/ cmd)+E并让更新 pass ,再按ctrl+E你会看到一些直方图,较大的条形意味着你的应用程序滞后/janky,然后你可以点击条形查看所有调用的函数的堆栈跟踪从而得到优化。
希望有帮助:)

于 2013-08-06T10:25:09.937 回答
2

如果您想要“正在加载...请稍候”对话框,只需添加以下内容:

<div id="loading_overlay" style="z-index:10000;background-color:#000;opacity:0.5;display:none;cursor:wait;">
    <div style="z-index:10001;background-color:#FFF;opacity:1;cursor:auto;position:absolute;top:50%;left:50%;height:300px;width:300px;margin-top:-150px;margin-left:-150px;">Please wait, loading...</div>
</div>

(显然,不要在您的实际文档中使用内联样式,将它们放在您的外部 CSS 文件中)

然后就在您的$.get('updatetable.php', function(data)行之前添加$("#loading_overlay").show();,然后$("#loading_overlay").hide();之后$table.trigger("update", [true]);(我假设这是您的 AJAX 请求的最后一行)。

基本上,您在 AJAX 请求之前显示加载对话框,然后在完成后将其隐藏。

并没有解决滞后问题,但它确实显示了一个加载对话框,因此用户知道为什么浏览器已锁定(如您所问)。

于 2013-08-05T16:58:46.380 回答
1

我唯一的结论是使输出的大小小于 400-500kb。

于 2013-08-01T14:10:22.503 回答