บางงานต้องใช้เวลาในการทำงาน ถ้าปล่อยให้ user รออย่างเดียวก็จะกังวลว่ามันจะทำงานสำเร็จหรือมี error รึเปล่า เคยเขียนวิธี jQuery Ajax แบบอนุกรมตามลำดับ ไว้ แต่อาจจะไม่เหมาะถ้า task บางอย่างมันยาวนานกว่านั้น ถึงลองเขียนแบบ flush stream / streaming ดู
ตัวจำลองเวลาโหลดโดยสุ่มถ่วงเวลาให้เหมือนจริง
<?php set_time_limit (0) ; header ('Cache-Control: no-cache') ;
header ('Content-Type: text/event-stream') ; function task ($ad, $message, $progress = '') { $data = [ 'id' => $ad, 'message' => $message, 'progress' => $progress, ]; echo json_encode ($data) ; ob_flush () ; flush () ;
} /* loop processing */
for ($a = 1; $a <= 10; $a++) { task ($a, 'on iteration ' . $a . ' of 10', $a * 10) ; sleep (rand (1, 10)) ;
} task ('CLOSE', 'Process complete') ;
ตัวอย่างการใช้ jQuery.ajax ()
<!DOCTYPE>
<html> <head> <title>Flushed ajax test</title> <meta charset="UTF-8" /> <style> #results { background: #eee; border: 1px solid #c00000; height: 250px; overflow: auto; padding: 10px; width: 98%; } </style>
</head> <body> <div id="results" style=""></div> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script> var last_response_len = false; $.ajax ('stream.php', { xhrFields: { onprogress: function (e) { var this_response, response = e.currentTarget.response; if (last_response_len === false) { this_response = response; last_response_len = response.length; } else { this_response = response.substring (last_response_len) ; last_response_len = response.length; } console.log (this_response) ; data = $.parseJSON (this_response) ; console.log (data) ; $ ('#results') .append ('<br>' + data.message) ; } } }) .done (function (data) { console.log ('Complete response = ' + data) ; $ ('#results') .append ('<br><br>Complete response = ' + data) ; }) .fail (function (data) { console.log ('Error: ', data) ; }) ; console.log ('Request Sent') ; </script>
</body> </html>
ถ้าดูใน console.log จะเห็นว่าตัวแปร data มันจะโดนเพิ่มขึ้นมาเรื่อง ๆ ดังนั้นถ้ามี response มาจาก server เยอะ ๆ ก็ต้องแก้ไข code ด้วย
update วิธีเขียนให้ง่ายขึ้นและทำงานบน nginx ได้ ตามที่เขียนใน NGINX: แสดงผลลัพธ์ทันที
<?php set_time_limit (0) ; header ('Cache-Control: no-cache') ;
header ('Content-Type: text/event-stream') ;
header ('X-Accel-Buffering: no') ; set_time_limit (0) ; ob_implicit_flush (true) ;
ob_end_flush () ; function task ($ad, $message, $progress = '') { $data = [ 'id' => $ad, 'message' => $message, 'progress' => $progress, ]; echo json_encode ($data) ;
} /* loop processing */
for ($a = 1; $a <= 10; $a++) { task ($a, 'on iteration ' . $a . ' of 10', $a * 10) ; sleep (rand (1, 10)) ;
} task ('CLOSE', 'Process complete') ;