บางงานต้องใช้เวลาในการทำงาน ถ้าปล่อยให้ user รออย่างเดียวก็จะกังวลว่ามันจะทำงานสำเร็จหรือมี error รึเปล่า เคยเขียนวิธี jQuery Ajax แบบอนุกรมตามลำดับ ไว้ แต่อาจจะไม่เหมาะถ้า task บางอย่างมันยาวนานกว่านั้น ถึงลองเขียนแบบ flush stream / streaming ดู
ตัวจำลองเวลาโหลดโดยสุ่มถ่วงเวลาให้เหมือนจริง
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | <?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()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | <! 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 > 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: แสดงผลลัพธ์ทันที
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <?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