2016-12-27 88 views
0

我正在從一個數據庫中提取許多記錄並呈現給一個表的應用程序。這是通過AJAX調用完成的,並將它們追加到已經存在的結果的末尾。AJAX - 大量響應鎖定瀏覽器後追加數據

這種情況下記錄的數量是變量,根據搜索條件的返回值可能是10或20,000。

現在,首先要做的事情。據我所知,網頁上有20,000條記錄並不明智,但這是要求所有記錄都可以在此頁面上看到,修改或標記的要求。

對PHP頁面的AJAX調用很好,看起來很快。然而,瓶頸是通過AJAX接收到的數據添加到DOM。

在下面的代碼中,您將看到創建錶行並將其返回給AJAX調用的主函數。

/* 
    Create Table Rows 
*/ 
function createTableRows($dashboardID, $type){ 

    // Timer 
    $start = microtime(true); 

    // Dashboard 
    $dashboardID = $_REQUEST['dashboardID']; 
    $objDB = new DB; 
    $objData = $objDB 
    -> setStoredProc('RenderDashboard') 
    -> setParam('dashboardID', $dashboardID) 
    -> setParam('limit', $_REQUEST['limit']) 
    -> setParam('offset', $_REQUEST['offset']) 
    -> setParam('actor', '1234') 
    -> execStoredProc() 
    -> parseXML(); 

    // Fetch other data 
    $markupData = fetchMarkup($dashboardID); 
    $exportFields = fetchExportFields($dashboardID); 
    $ignore = Array('identifierQID', 'identifierNTID'); 

    // Vars 
    $outputArray = Array(); 
    $recordCount = 0; 
    $i = 0; 

    // Loop over our data 
    foreach($objData->data as $r){ 

     $outputArray[$i++] = '<tr data-qid="'.$r->identifierQID.'" class="primaryValue ' . searchMarkup($markupData, $r->identifierQID) . '">'; 

     // Loop over our fields 
     foreach($r as $key => $value){ 

      // Vars 
      $fieldID = str_replace('_', '', $key); 

      // Don't include our identifier columns 
      if(!in_array($fieldID, $ignore)){ 
      $outputArray[$i++] = '<td data-tableexport-display="always" class="small' . ($exportFields ? (in_array($fieldID, $exportFields) ? ' hidden' : '') : '') . '">' . formatFieldData($fieldID, $value) . '</td>'; 
      } 

     } 

     // Notes always come last 
     $outputArray[$i++] = '<td data-tableexport-display="always" class="notesTD allowContext hidden"></td>'; 

     $outputArray[$i++] = '</tr>'; 
     $recordCount++; 

    } 

    // Join our rows array and return it 
    $end = microtime(true); 
    $timer = number_format($end - $start, 2); 
    return array(join("",$outputArray), $recordCount, $timer); 
} 

// This is what gets passed back to our AJAX call on the UI 
echo createTableRows($dashboardID)[0]; 

這裏是Javascript處理它收到的迴應。

// Given data, create our table rows 
function createRows(data) { 

    // Update Progress Bar 
    $('[name=progressDiv]').show(); 

    // Append the results to the DOM 
    /* THIS IS WHAT IS KILLING THE SPEED!!!!*/ 
    $('[name=resultsTable]').append(data); 

    // If our total number of records exceeds the threshold, we will be using the progress bar for the status 
    if (totalRecords > maxThreshold) { 
     $('[name=resultsProgress]').attr('aria-valuenow', currentPage/totalPages * 100) 
      .css('width', currentPage/totalPages * 100 + '%') 
      .text((currentPage < totalPages ? recordsPerPage * currentPage + ' of ' + totalRecords + ' records loaded' : 'Loaded ' + totalRecords + ' records!')); 
    } else { 
     // Loaded all records in one shot, update progress bar 
     $('[name=resultsProgress]').attr('aria-valuenow', 100) 
      .css('width', '100%') 
      .text('Loaded ' + totalRecords + ' records!') 
      .removeClass('active'); 
    } 
    // Do we have more data to load? 
    if (currentPage < totalPages && totalRecords > maxThreshold) { 
     // Allow a little time for the progress to update before locking up 
     setTimeout(function(){ 
     fetchMore(); 
     }, 100); 

    } 

    // After the table has been appended to the DOM, run clean up to enable any additional functionality 
    cleanUp(); 
} 

的問題:

的問題是,APPEND被鎖定瀏覽器並導致直到附加已經完成它是反應遲鈍。我已經分解了所以它會批量獲取數據,但這不是問題,它處理響應中的行。

問題:

有沒有辦法來處理批次的結果,並追加,如果沒有它鎖定了瀏覽器嗎?它自己的反應只是附加到我的表的TBODY後面的一堆TR。我最後的手段是不得不分頁。如果我能解決這個問題,我可以說服他們爲更大的數據集進行分頁。

我想我正在尋找一種方法來以更好的格式返回結果,以便追加或分解響應,並在批量追加時另一個AJAX調用正在獲取更多要處理的數據。

想法?

+1

將大量行附加到表中將始終是殺手鐗。 – epascarello

+0

窗口。requestAnimationFrame(fetchMore); –

+0

作爲用戶滾動,您可以等待加載更多嗎? –

回答

0

可能把它推到瀏覽器qeue:

function createRows(data){ 
JSON.parse(data); 
for(elem in data){ 
(function(){ 
var el=elem; 
setTimeout(function(){ 
    document.body.innerHTML+="<tr>"+el+"</tr>"; 
},0); 
})(); 
} 
} 

需要的數據是一個JSON數組,可能只是返回一個字符串數組,可以處理:

["<td>User 1</td>","<td>User 1</td>","<td>User 1</td>"] 

解決方法二:完全在服務器端生成:

<progress value="0" max="100" id="prog"> 
<iframe id="data" iframe src="yourdata"> 
</iframe> 

$("#data").on("load",function(){ 
    $("#prog").val(100); 
}); 
+0

這就是發生的事情。第一次調用X量,然後檢查是否有更多要加載。在處理這個問題的PHP代碼中有一個'fetchMore'函數。它最終所做的就是將這些數據傳回給JavaScript,以再次追加它,這是我現在使用的同一條船。 – SBB

+0

但是沒有更好的辦法... –

+0

iframe是一個有趣的概念,但仍然需要我的批量頁面上的數據。加載大量數據只會導致iFrame成爲白頁,直到PHP加載每條記錄,而不是批量執行。那個窗口中的JavaScript會凍結用戶需要與之交互的主要結果,就像它現在一樣? – SBB