บางงานต้องใช้เวลาในการทำงาน ถ้าปล่อยให้ 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') ;