开发者

web browser become slow or no response after several ajax calls

I'm totally newbie to jquery and ajax, my recently project is to help the representatives (reps) to manage customer quotations online. I have a page which displays all the quotations in a big table.

I've managed to use ajax to fetch and display the quotations which associate to a particular rep after i click that rep's name. But the only problem is the speed of response. The first few clicks are ok and very smooth. But after several tries, the response become slow and I cant even scroll down the webpage, and later on the web browser craches....

Please have a look at my ajax code. here it is:

<!-- Data display area -->
<br /><input type="image" id="printbtn" value="Print" src="images/printer.png"/><br />

  <div id="container">
    <div id="content">

    </div>  
  </div>  
<!-- Data display area -->  

<!-- AJAX FETCH QUOTES DATA + Tablesorter + FIXED TABLE HEADER--> 
<script type="text/javascript">
//<![CDATA[ 
$(function(){

$("a.repID").click(function(){ 
    $('div#loader').append("<p align='center'><img src='images/loadingbar2.gif' id='loading' /></p>"); 
 var repID = $(this).attr("title");   

$.ajax({
    type:'POST',
    url:'quote_info.php',
    data:'repID=' + repID,
    cache: false,

    success:function(data)
    {
       $("#container").html('<div id="content">' + data + '</div>');
       $("#loading").fadeOut(500, function() {$(this).remove();});
       $("#sortme").tablesorter();
       $('.tbl').fixedtableheader(); 
    }
});
return false;
});
});
</script>
<!-- AJAX FETCH QUOTES DATA + Tablesorter + FIXED TABLE HEADER-->

Problem found, the tablesorter and fixed header inside the success handler are causing the problem, but if I put them outside the handler, they will not work, where should i put them? or how should i do to have that two functions, many thanks!!!!

Server side php code:

<?php
header('Content-Type: text/html; charset=ISO-8859-1');
$conn=mysql_connect("localhost","root","");
mysql_select_db("auma",$conn);

$repID = $_POST['repID'];

if ($repID == "All") {
    $whereClause = "";
} else {
    $whereClause = "WHERE repID='$repID'";
} 

$quoteinfoSQL = "SELECT q.quoteWeek, q.quoteID, q.quoteRev, q.customerName, q.repID, 
             q.quoteDesc, q.quoteValue, q.quoteProject, q.quotePM, q.quoteDR, q.quoteDS, 
             a.followUp, a.quoteStatus, a.furtherAction, a.UKConNo, a.clientRef, a.CorS  
             FROM auma_quote q 
             INNER JOIN auma_action a on a.quoteID = q.quoteID 
             $whereClause  
             ORDER BY q.quoteWeek DESC, q.quoteID DESC";



// execute the statement
$rsQuoteinfo = mysql_query( $quoteinfoSQL );

$html.= "<br />";

if ($repID == "All") {
    $html.= "<img src=\"images/users.png\" />&nbsp; Quotations from all representatives.</h6>";
} else {
    $html.= "<img src=\"images/users.png\" />&nbsp; Quotations from <b>$repID</b>.</h6>";
} 



$html.= "<br />";


$html.= "<table id=\"sortme\" class=\"tbl\">";
$html.= "<thead>";
$html.= "<tr>
         <th>Week</th>
         <th>Quote ID</th>
         <th>Rev</th>
         <th>Customer</th>
         <th>Rep ID</th>
         <th>Description</th>
         <th>Gross Value</th>
         <th>Project</th>
         <th>GP%</th>
         <th>Date Received</th>
         <th>Date Sent</th>
         <th>Follow up Action</th>
         <th>Result</th>
         <th>Further Action</th>
         <th>UK Contract No.</th>
         <th>Client Ref.</th>
         <th>Contractor or Specification</th>
         <th></th>
         </tr>";
$html.= "</thead>";
$html.= "<tbody>";

while($quoteinfoRow = mysql_fetch_array($rsQuoteinfo)){
    $quoteWeek = $quoteinfoRow['quoteWeek'];
 开发者_开发知识库   $quoteRev = $quoteinfoRow['quoteRev'];
    $customerName = htmlspecialchars($quoteinfoRow['customerName']);
    $repIDs= $quoteinfoRow['repID'];
    $quoteID= $quoteinfoRow['quoteID'];
    $quoteDesc = htmlspecialchars($quoteinfoRow['quoteDesc']);
    $quoteValue = htmlspecialchars($quoteinfoRow['quoteValue']);
    $quoteProject = htmlspecialchars($quoteinfoRow['quoteProject']);
    $quotePM = $quoteinfoRow['quotePM'];
    $quoteDR = $quoteinfoRow['quoteDR'];
    $quoteDS = $quoteinfoRow['quoteDS'];
    $followUp = htmlspecialchars($quoteinfoRow['followUp']);
    $quoteStatus = htmlspecialchars($quoteinfoRow['quoteStatus']);
    $furtherAction = htmlspecialchars($quoteinfoRow['furtherAction']);
    $UKConNo = $quoteinfoRow['UKConNo'];
    $clientRef = $quoteinfoRow['clientRef'];
    $CorS = htmlspecialchars($quoteinfoRow['CorS']);

    $html.= "<tr>";
    $html.= "<td>$quoteWeek</td>";
    $html.= "<td>$quoteID</td>";
    $html.= "<td>$quoteRev</td>";
    $html.= "<td>$customerName</td>";    
    $html.= "<td>$repIDs</td>";
    $html.= "<td>$quoteDesc</td>";
    $html.= "<td>$quoteValue</td>";
    $html.= "<td>$quoteProject</td>";
    $html.= "<td>$quotePM</td>";
    $html.= "<td>$quoteDR</td>";
    $html.= "<td>$quoteDS</td>";
    $html.= "<td>$followUp</td>";
    $html.= "<td>$quoteStatus</td>";
    $html.= "<td>$furtherAction</td>";
    $html.= "<td>$UKConNo</td>";
    $html.= "<td>$clientRef</td>";
    $html.= "<td>$CorS</td>";

    $html.= "<td align=\"center\"><a href=\"quotedetails.php?quoteID=$quoteID&amp;customerName=$customerName\" ><input type=\"image\" src=\"images/edit.png\" /></a></td>";

    $html.= "</tr>";
}  // while



$html.= "</tbody>";
$html.= "</table>";
$html.= "<br />";
echo $html;


?>

Response sample from Firebug:

<br /><img src="images/users.png" />&nbsp; Quotations from <b>NA</b>.</h6>
<br />
<table id="sortme" class="tbl">
<thead>
<tr>

         <th>Week</th>

         <th>Quote ID</th>

         <th>Rev</th>

         <th>Customer</th>

         <th>Rep ID</th>

         <th>Description</th>

         <th>Gross Value</th>

         <th>Project</th>

         <th>GP%</th>

         <th>Date Received</th>

         <th>Date Sent</th>

         <th>Follow up Action</th>

         <th>Result</th>

         <th>Further Action</th>

         <th>UK Contract No.</th>

         <th>Client Ref.</th>

         <th>Contractor or Specification</th>

         <th></th>

         </tr>
</thead>
<tbody>
<tr>
<td>9</td>
<td>Q42389</td>
<td>0</td>
<td>Worldwide Procurement Services Ltd</td>
<td>NA</td>
<td>1 x Motor (Z011.274)</td>
<td>£2,954</td>
<td>COM: 649862</td>
<td>spares net</td>
<td>2010-02-28</td>
<td>2010-03-03</td>
<td></td>
<td>ORDERED</td>
<td></td>
<td>28824</td>
<td></td>
<td></td>
<td align="center"><a href="quotedetails.php?quoteID=Q42389&amp;customerName=Worldwide Procurement Services Ltd" ><input type="image" src="images/edit.png" /></a></td>
</tr>
<tr>
<td>1</td>
<td>Q41883</td>
<td>1</td>
<td>Ital (International Trading Alliance) Ltd</td>
<td>NA</td>
<td>1xSAM10.1E75</td>
<td>£2,059</td>
<td>COM: 553697</td>
<td>25% net</td>
<td>2010-01-05</td>
<td>2010-01-08</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td align="center"><a href="quotedetails.php?quoteID=Q41883&amp;customerName=Ital (International Trading Alliance) Ltd" ><input type="image" src="images/edit.png" /></a></td>
</tr>
</tbody>
</table>
<br />


Mmmh not quite sure but if you are not removing (or overwriting) #sortme or .tbl every time, then these lines might be related to your performance problem:

$("#sortme").tablesorter();
$('.tbl').fixedtableheader();

I have no insight in these functions but it could be that you bind handlers to the elements every time you do the Ajax call. Just bind them once and see if it gets better.

Update:

Maybe it is sufficient to put them outside, e.g.:

$(function() {
    $("#sortme").tablesorter();
    $('.tbl').fixedtableheader();

    $("a.repID").click(function(){...});  
});

As for the tablesorter plugin, it has an update method (see examples), so you can put this inside your success method:

success: function(date) {
    //...
    $("#sortme").trigger("update"); 
}


You are vulnerable to SQL injection:

$repID = $_POST['repID'];

[...]

$whereClause = "WHERE repID='$repID'";


Without walking through the code in my head...I can tell you that your Javascript is more than likely presenting a memory leak.

Try tuning your Javascript code to better handle the objects its creating and you should notice an improvement. Here's an article (that links to a couple of other good articles as well) to get you started:

Resolving JavaScript Memory Leaks


Given just the information in your question, it's hard to know what the source of the slowdown is.

Personally I would use Firebug to "profile" the code by stepping through important lines. Set a breakpoint on the $.ajax({ line as well as in the success handler (on the $("#container").html('<div id="content">' + data + '</div>'); line). When inside the success handler, and stopped on that first line, click the "step over" button of Firebug to see how long it takes to execute each line. Also, if there is a large time delay between the sending of the AJAX request and execution of the success handler, then your server-side script may be a major contributor to the performance degradation.

One small thing that you can do right away: move the id='loading' attribute from the <img> tag to the <p> tag. The $("#loading").fadeOut(500, function() {$(this).remove();}); is basically causing a <p> element to "leak" with every call to the success handler and $('div#loader').append(".... Your success handler is not properly cleaning up.


Your scripting appears to be ok, but I'm wondering if your data could possibly have any single quotes inside of it?


I had a problem with data overload with my tables. It would take up to 10 seconds to load my tables. So I used a 3rd-party data table tool. It does server-side scripting. Well worth the time to implement.

Get rid of the cdata remark tag at the start of script block. Use Firebug and see if it is loading the click event more than once. Select script tab in Firebug each time you click. I bet you have memory leak.


I used the additional information that you have provided to write up a test case (http://pastebin.com/6S3RU0Fs). Using this test case, each time that I click the "click" link, the web browser process comsumes more and more memory which it does not release back to the operating system, indicating a memory leak. Commenting out line 15 causes the memory leak issue to disappear, so I'm pretty sure that the problem is in the fixedtableheader plugin.

You can still use the fixedtableheader plugin as long as you don't call fixedtableheader() multiple times. Instead, you can use the "update" functionality of the tablesorter plugin. To do this, you need to modify your PHP and Javascript somewhat.

The PHP script is altered to only output the table rows:

<?php
header('Content-Type: text/html; charset=ISO-8859-1');
$conn=mysql_connect("localhost","root","");
mysql_select_db("auma",$conn);

$repID = $_POST['repID'];

if ($repID == "All") {
    $whereClause = "";
} else {
    $whereClause = "WHERE repID='" . mysql_real_escape_string($repID, $conn) . "'";
} 

$quoteinfoSQL = "SELECT q.quoteWeek, q.quoteID, q.quoteRev, q.customerName, q.repID, 
             q.quoteDesc, q.quoteValue, q.quoteProject, q.quotePM, q.quoteDR, q.quoteDS, 
             a.followUp, a.quoteStatus, a.furtherAction, a.UKConNo, a.clientRef, a.CorS  
             FROM auma_quote q 
             INNER JOIN auma_action a on a.quoteID = q.quoteID 
             $whereClause  
             ORDER BY q.quoteWeek DESC, q.quoteID DESC";



// execute the statement
$rsQuoteinfo = mysql_query( $quoteinfoSQL, $conn );


while($quoteinfoRow = mysql_fetch_assoc($rsQuoteinfo)){
    $quoteWeek = $quoteinfoRow['quoteWeek'];
    $quoteRev = $quoteinfoRow['quoteRev'];
    $customerName = $quoteinfoRow['customerName'];
    $repIDs= $quoteinfoRow['repID'];
    $quoteID= $quoteinfoRow['quoteID'];
    $quoteDesc = $quoteinfoRow['quoteDesc'];
    $quoteValue = $quoteinfoRow['quoteValue'];
    $quoteProject = $quoteinfoRow['quoteProject'];
    $quotePM = $quoteinfoRow['quotePM'];
    $quoteDR = $quoteinfoRow['quoteDR'];
    $quoteDS = $quoteinfoRow['quoteDS'];
    $followUp = $quoteinfoRow['followUp'];
    $quoteStatus = $quoteinfoRow['quoteStatus'];
    $furtherAction = $quoteinfoRow['furtherAction'];
    $UKConNo = $quoteinfoRow['UKConNo'];
    $clientRef = $quoteinfoRow['clientRef'];
    $CorS = $quoteinfoRow['CorS'];

    $html.= "<tr>";
    echo "<td>" . htmlspecialchars($quoteWeek) . "</td>";
    echo "<td>" . htmlspecialchars($quoteID) . "</td>";
    echo "<td>" . htmlspecialchars($quoteRev) . "</td>";
    echo "<td>" . htmlspecialchars($customerName) . "</td>";    
    echo "<td>" . htmlspecialchars($repIDs) . "</td>";
    echo "<td>" . htmlspecialchars($quoteDesc) . "</td>";
    echo "<td>" . htmlspecialchars($quoteValue) . "</td>";
    echo "<td>" . htmlspecialchars($quoteProject) . "</td>";
    echo "<td>" . htmlspecialchars($quotePM) . "</td>";
    echo "<td>" . htmlspecialchars($quoteDR) . "</td>";
    echo "<td>" . htmlspecialchars($quoteDS) . "</td>";
    echo "<td>" . htmlspecialchars($followUp) . "</td>";
    echo "<td>" . htmlspecialchars($quoteStatus) . "</td>";
    echo "<td>" . htmlspecialchars($furtherAction) . "</td>";
    echo "<td>" . htmlspecialchars($UKConNo) . "</td>";
    echo "<td>" . htmlspecialchars($clientRef) . "</td>";
    echo "<td>" . htmlspecialchars($CorS) . "</td>";

    echo "<td align=\"center\"><a href=\"" . htmlspecialchars("quotedetails.php?quoteID=" . urlencode($quoteID) . "&customerName=" . urlencode($customerName)) . "\" ><input type=\"image\" src=\"images/edit.png\" /></a></td>";

    echo "</tr>";
}  // while

Note that I made some changes for efficiency and security:

  • Use mysql_fetch_assoc rather than mysql_fetch_array because you aren't indexing columns by number.
  • echo the HTML directly rather than building up the $html string, which is echoed anyway.
  • Escape all user input with mysql_real_escape_string if it is used to build an SQL query (helps prevent SQL injection attacks).
  • Consistently escape all text from databases and user input with htmlspecialchars and/or urlencode if it is sent back as HTML (helps prevent script injection/XSS).

Your Javascript is altered by moving the static HTML into the HTML file, calling tablesorter() and fixedtableheader() only once each on page load, using the data from the PHP script to set the inner HTML of the #sortme <tbody>, and triggering the "update" event on #sortme. I have modified the test case to show you what I mean (http://pastebin.com/qFn2jRLB).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜