2011-08-02 77 views
4

我想要一個基於服務器端請求狀態更新的jQuery進度條。我基於this tutorial的代碼,但它使用文件上傳器作爲其基礎(與this問題相同)。如果沒有文件上傳器,我無法讓它工作。問題是進度條只會在process.php完成後纔會更新。它不是異步地要求更新進展,而是等待整個過程的完成。我只看到數據:數據警報一次。jquery progressbar - 一次加載全部

任何想法?

網頁:

<form id="upload-form" action='process.php' method="post" target="upload-frame"> 
<input type="hidden" id="uid" name="UPLOAD_IDENTIFIER" value="<?php echo $uid; ?>" > 
<input type="submit" value="Submit" /> 
</form> 

<div id="progressbar"></div> 

<iframe id="upload-frame" name="upload-frame" style="display:none"></iframe> 

Process.php - 由AJAX請求調用 - 當表單提交

<?php 
session_start(); 
$varArray=array(1,2,3,4); 
$_SESSION['total']=count($varArray); 

foreach($varArray as $val){ 
    $_SESSION['current']=$val; 
    sleep(2); 
} 
?> 

的javascript

$(document).ready(function() { 
    var started = false;// This flag determines if the upload has started 
    $(function() { 
     // Start progress tracking when the form is submitted 
     $('#upload-form').submit(function() { 
      $('#progressbar').progressbar();// Initialize the jQuery UI plugin 

      // We know the upload is complete when the frame loads 
      $('#upload-frame').load(function() { 
       // This is to prevent infinite loop 
       // in case the upload is too fast 
       started = true; 
       // Do whatever you want when upload is complete 
       alert('Upload Complete!'); 
      }); 

      // Start updating progress after a 1 second delay 
      setTimeout(function() { 
       // We pass the upload identifier to our function 
       updateProgress($('#uid').val()); 
      }, 1000); 
     }); 
    }); 

    function updateProgress(id) { 
     var time = new Date().getTime(); 
     // Make a GET request to the server 
     // Pass our upload identifier as a parameter 
     // Also pass current time to prevent caching 
     $.ajax({ 
      url: 'getProgress.php', 
      type: "GET", 
      cache: false, 
      data: {'uid':id}, 
      dataType: 'text', 
      success: function(data){ 
       alert("data: " + data); 
       var progress = parseInt(data, 10); 
       if (progress < 100 || !started) { 
        // Determine if upload has started 
        started = progress < 100; 
        // If we aren't done or started, update again 
        updateProgress(id); 
       } 
       // Update the progress bar percentage 
       // But only if we have started 
       started && $('#progressbar').progressbar('value', progress); 
      } 
     }); 
    } 
}(jQuery)); 

getProgress.php稱爲:

<?php 
session_start(); 
if (isset($_REQUEST['uid'])) { 
    if (isset($_SESSION['total']) && isset($_SESSION['current'])) { 
     // Fetch the upload progress data 
     $total = $_SESSION['total']; 
     $current = $_SESSION['current']; 
     // Calculate the current percentage 
     $percent_done = round($current/$total*100); 
     echo $percent_done; 
    }else{ 
     echo 100;// If there is no data, assume it's done 
    } 
} 
?> 

回答

6

AFAIK,PHP會話實際上是同步的。這意味着Process.php腳本阻止了getProgress.php腳本的運行,直到Process.php與會話完成。

那麼什麼情況是:

  1. Process.php開始,並呼籲在session_start()
  2. ,服務器對會話控制在session_start()
  3. getProcess.php開始,並呼籲在session_start()
  4. 服務器阻止getProcess.php,直到會話未使用。
  5. Process.php完成並關閉會話。
  6. 服務器恢復getProcess.php併爲其提供對會話的控制。
  7. getProcess.php現在看到該過程已完成。

參見http://www.php.net/manual/en/function.session-write-close.php

會話數據通常存儲在將腳本終止,而無需調用session_write_close(),但作爲會話數據被鎖定,以防止併發只寫腳本可以在任何時間上的會話操作。 [...]

我沒有測試過下面的代碼,因爲我沒有在時刻訪問服務器,但我想事端像它應該工作:

<?php 
$varArray=array(1,2,3,4); 
session_start(); 
$_SESSION['total']=count($varArray); 
session_write_close(); 

foreach($varArray as $val){ 
    session_start(); 
    $_SESSION['current']=$val; 
    session_write_close(); 
    sleep(2); 
} 
?> 
+0

真棒。我在process.php中的兩個會話變量定義周圍包裝了'session_start()'和'session_write_close()',它以我期望的方式工作。美麗! – Andrea