หมวดหมู่: jQuery

jQuery: Ajax รับข้อมูลแบบ streamjQuery: Ajax รับข้อมูลแบบ stream

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