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