簡體   English   中英

jQuery.post動態數據回調函數

[英]jQuery.post dynamic data callback function

我有一個腳本,需要幾秒鍾的處理,最多約一分鍾。 該腳本調整圖像數組的大小,銳化它們並最終將它們拉鏈以供用戶下載。

現在我需要某種進度信息。 我在想,使用jQuery的.post()方法,回調函數中的數據會逐步更新,但這似乎不起作用。

在我的例子中,我只是使用循環來模擬我的腳本:

        $(document).ready(function() {
            $('a.loop').click(function() {
                $.post('loop.php', {foo:"bar"},
                function(data) {
                    $("div").html(data);                        
                });
                return false;
            });
        });

loop.php:

for ($i = 0; $i <= 100; $i++) {
    echo $i . "<br />";
}
echo "done";

更新:獲取進度信息要容易得多,因為jQuery Ajax請求具有promise接口。 使用這個答案:

https://stackoverflow.com/a/32272660/18771


以下原始答案已過時(最初來自2010年)。 它仍然有效,但比它需要的更復雜。 我會保留它以供參考和比較。


您需要來自服務器的某種進度信息。 ajax回調不會執行漸進式工作,只會在請求成功返回后觸發一次。

所以...在PHP中你需要這樣的東西:

/* progress.php */
$batch_done = some_way_to_find_out_that_number();
$batch_size = some_way_to_find_out_that_number_too();
header('Content-type: application/json');
// TODO: format number
echo '{"progress":'. ($batch_size==0 ? '0' : $batch_done*100.0/$batch_size).'}';

為此,您的圖像處理腳本必須留下一些進展的證據。

在JavaScript中是這樣的:

$(document).ready(function() {
  $('a.loop').click(function() {
    var queryData = {foo:"bar"};
    // prepare a function that does cyclic progress checking
    var progressCheck = function() {
      $.getJSON(
        "progress.php", queryData,
        function(data) { 
          $("div.progress").css("width", data.progress+"%");
        }
      )
    };
    $.post(
      'loop.php', queryData,
      /* create the post request callback now */
      function(intvalId){
        return function(data) {
          $("div").html(data);
          clearInterval(intvalId);
        }
      }( setInterval(progressCheck, 1000) )
    );
    return false;
  });
});

這部分需要一些解釋:

function(intvalId){
  return function(data) {
    $("div").html(data);
    clearInterval(intvalId);
  };
}( setInterval(progressCheck, 1000) )

function(intvalId)是一個匿名函數,它接受一個參數 - 一個區間ID。 此ID是停止通過setInterval()設置的間隔所必需的。 幸運的是,對setInterval()的調用返回了這個ID。

匿名外部函數返回一個內部function(data) ,這個function(data)將是$.post()的實際回調function(data)

我們立即調用外部函數,在此過程中執行兩項操作:使用setInterval()觸發間隔並將其返回值(ID)作為參數傳遞。 內部函數在其調用時可以使用此參數值(可能在將來幾分鍾內)。 post()的回調現在實際上可以停止間隔。

作為鍛煉對你;)

  • 修改ajax調用,使其在請求錯誤或超時時停止間隔。 目前,如果回調從未運行(並且僅在成功運行!),則間隔將永遠不會停止。
  • 確保無法無意中觸發post()兩次。

感謝Tomalak,我終於把一些有用的東西放在了一起。 由於我在處理批處理時實際上並沒有在服務器上編寫我的圖像文件,因此我在progress.php腳本中編寫了一個日志文件。

我想知道這是否是最好的方法。 我想避免寫入文件並嘗試使用PHP的$ _session,但似乎無法逐步讀取它。 這可能是$ _session嗎?

HTML:

<a class="download" href="#">request download</a>
<p class="message"></p>

JS:

$('a.download').click(function() {
    var queryData = {images : ["001.jpg", "002.jpg", "003.jpg"]};

    var progressCheck = function() {
        $.get("progress.php",
            function(data) {
                $("p.message").html(data); 
            }
        );
    };

    $.post('proccess.php', queryData,
        function(intvalId) {
            return function(data) {
                $("p.message").html(data);
                clearInterval(intvalId);
            }
        } (setInterval(progressCheck, 1000))
    );

    return false;
});

process.php:

$arr = $_POST['images'];
$arr_cnt = count($arr);
$filename = "log.txt";

$i = 1;
foreach ($arr as $val) {
    $content = "processing $val ($i/$arr_cnt)";

    $handle = fopen($filename, 'w');
    fwrite($handle, $content);
    fclose($handle);

    $i++;
    sleep(3); // to mimic image processing
}

echo "<a href='#'>download zip</a>";

progress.php:

$filename = "log.txt";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);

echo $contents; 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM