PlusMagi's Blog By Pitt Phunsanit Backend,Database jQuery: Ajax รับข้อมูลแบบ stream

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

SQL

-- 1. ประกาศ Cursor เพื่อจำกัดการดึงข้อมูลเป็นชุดย่อย<br>DECLARE data_cursor CURSOR FOR SELECT id, name, value FROM large_dataset WHERE status = 'active';<br><br>-- 2. เปิด Cursor และเริ่มดึงข้อมูลเป็นชุด (Batching)<br>OPEN data_cursor;<br>FETCH data_cursor INTO batch_data LIMIT 100; -- ดึงมาทีละ 100 แถว<br>-- ใน Backend จะมีการวนลูป (LOOP) เพื่อดึงข้อมูลชุดถัดไปจนกว่าจะหมด<br>-- ตัวอย่างการส่งผลลัพธ์เป็น JSON Array (100 records) ที่ Backend จะรับไปต่อ<br>SELECT json_agg(t) FROM (VALUES ('1,2,3'), ('4,5,6')) AS t(data_chunk);<br>-- 3. ปิด Cursor เมื่อเสร็จสิ้น<br>CLOSE data_cursor;

💻 การรับ Stream ด้วย jQuery Ajax

“>

แทนที่จะใช้ $.ajax แบบปกติที่รอ Response ทั้งหมด เราต้องใช้ XMLHttpRequest (XHR) โดยตรงเพื่อจัดการ Event ของการรับข้อมูลเป็นก้อน (Chunk) ซึ่งเป็นหัวใจของการ Streaming:

JavaScript

// 1. สร้าง XHR Object<br>const xhr = new XMLHttpRequest();<br><br>// 2. กำหนด Event Handler เมื่อได้รับข้อมูล<br>xhr.onload = function() {<br>    // ข้อมูลทั้งหมดถูกรับมาแล้ว (กรณีที่เซิร์ฟเวอร์ปิด Stream)<br>    console.log('Stream Complete:', this.responseText);<br>    // นำข้อมูลสุดท้ายไปแสดงผล<br>    document.getElementById('results').innerHTML = this.responseText;<br>};<br><br>// 3. กำหนด Event Handler เมื่อได้รับข้อมูลเป็นชิ้น (Chunk) - สำคัญที่สุด<br>xhr.onprogress = function(event) {<br>    if (event.lengthComputable) {<br>        const loaded = event.loaded; // ขนาดข้อมูลที่โหลดมาแล้ว<br>        const total = event.total; // ขนาดรวม<br>        console.log('Progress:', Math.round((loaded / total) * 100) + '%');<br>        // ในความเป็นจริง: ต้องมีการ Parse ข้อมูลที่เข้ามาใน Chunk นี้และอัปเดต DOM<br>        // เช่น: displayChunk(event.data);<br>    }<br>};<br><br>// 4. เปิดการเชื่อมต่อและส่งคำขอ<br>xhr.open('GET', '/api/stream-data', true);<br>xhr.send();
“>

การใช้ onprogress คือกุญแจสำคัญที่ทำให้ Ajax สามารถรับข้อมูลแบบ Stream ได้อย่างแท้จริง ทำให้ UI ไม่ค้างและผู้ใช้เห็นการอัปเดตข้อมูลแบบ Real-time

✨ บทสรุปสำหรับ Senior Architect

“>

การทำ Streaming Data ไม่ใช่แค่การลดเวลาการโหลด แต่เป็นการปรับปรุง User Experience (UX) และ System Performance ในการจัดการ I/O ที่มีขนาดใหญ่ การออกแบบระบบที่ถูกต้องต้องเริ่มตั้งแต่การจัดการทรัพยากรที่ PostgreSQL (ใช้ Cursors) การส่งข้อมูลที่ Backend (ใช้ Streaming Response) และการรับข้อมูลที่ Client (ใช้ XHR onprogress) เพื่อให้มั่นใจว่าข้อมูลจะถูกประมวลผลและแสดงผลอย่างต่อเนื่อง ไม่ใช่การรอจนกว่างานทั้งหมดจะเสร็จสมบูรณ์

“>

ในโลกของการพัฒนาเว็บสมัยใหม่ การที่ระบบต้องประมวลผลข้อมูลขนาดใหญ่ หรือต้องรอการทำงานที่ใช้เวลานาน (เช่น การ Export รายงาน, การประมวลผลข้อมูลจำนวนมาก) เป็นเรื่องที่เกิดขึ้นเป็นประจำ หากเราปล่อยให้ผู้ใช้รอหน้าจอโหลดอย่างเดียว ประสบการณ์ผู้ใช้ (UX) จะลดลงอย่างมาก

“>

ทางแก้ไขคือการใช้เทคนิค Streaming Data หรือการรับข้อมูลแบบสตรีมมิ่ง (Stream) ซึ่งหมายถึงการที่เซิร์ฟเวอร์ไม่รอจนกว่างานจะเสร็จสมบูรณ์ แต่จะค่อย ๆ ผลัก (Push) ข้อมูลออกมาให้ไคลเอนต์รับทราบเป็นชิ้น ๆ ทันทีที่พร้อม ทำให้ผู้ใช้รู้สึกว่าระบบกำลังทำงานอย่างต่อเนื่องและรวดเร็ว

💡 หลักการทำงาน: Streaming Data จาก PostgreSQL ผ่าน Ajax

“>

เมื่อเราต้องการนำข้อมูลจำนวนมากจากฐานข้อมูล PostgreSQL มาแสดงผลแบบสตรีมมิ่ง เราต้องเข้าใจกระบวนการตั้งแต่ต้นทางถึงปลายทางอย่างลึกซึ้ง โดยมีองค์ประกอบหลัก 3 ส่วน:

  • PostgreSQL Layer (Source): ฐานข้อมูลต้องถูกเรียกใช้ในลักษณะที่สามารถส่งผลลัพธ์ออกมาเป็นชุดย่อย ๆ ได้อย่างต่อเนื่อง (เช่น การใช้ Cursors หรือการแบ่ง Batching) เพื่อไม่ให้เกิดการโหลดหน่วยความจำสูงเกินไป
  • Backend Layer (Bridge): ภาษาฝั่งเซิร์ฟเวอร์ (เช่น Node.js, PHP) จะทำหน้าที่เป็นตัวกลางในการเชื่อมต่อกับ PostgreSQL และรับข้อมูลมาทีละส่วน จากนั้นจึงส่งข้อมูลส่วนนั้นออกไปในรูปแบบ Response Stream
  • Client Layer (Consumer): ใช้ jQuery Ajax (โดยเฉพาะการจัดการ XMLHttpRequest) เพื่อรับข้อมูลที่ถูกส่งมาเป็นชิ้น ๆ (Chunk by Chunk) และนำไปอัปเดต DOM ทันที

⚙️ ตัวอย่างการจัดการข้อมูลแบบ Stream ใน PostgreSQL

“>

ในระดับ PostgreSQL เราจะใช้ DECLARE CURSOR เพื่อให้การดึงข้อมูลเป็นไปแบบ Iterative และจัดการหน่วยความจำได้ดี:

SQL

-- 1. ประกาศ Cursor เพื่อจำกัดการดึงข้อมูลเป็นชุดย่อย<br>DECLARE data_cursor CURSOR FOR SELECT id, name, value FROM large_dataset WHERE status = 'active';<br><br>-- 2. เปิด Cursor และเริ่มดึงข้อมูลเป็นชุด (Batching)<br>OPEN data_cursor;<br>FETCH data_cursor INTO batch_data LIMIT 100; -- ดึงมาทีละ 100 แถว<br>-- ใน Backend จะมีการวนลูป (LOOP) เพื่อดึงข้อมูลชุดถัดไปจนกว่าจะหมด<br>-- ตัวอย่างการส่งผลลัพธ์เป็น JSON Array (100 records) ที่ Backend จะรับไปต่อ<br>SELECT json_agg(t) FROM (VALUES ('1,2,3'), ('4,5,6')) AS t(data_chunk);<br>-- 3. ปิด Cursor เมื่อเสร็จสิ้น<br>CLOSE data_cursor;

💻 การรับ Stream ด้วย jQuery Ajax

“>

แทนที่จะใช้ $.ajax แบบปกติที่รอ Response ทั้งหมด เราต้องใช้ XMLHttpRequest (XHR) โดยตรงเพื่อจัดการ Event ของการรับข้อมูลเป็นก้อน (Chunk) ซึ่งเป็นหัวใจของการ Streaming:

JavaScript

// 1. สร้าง XHR Object<br>const xhr = new XMLHttpRequest();<br><br>// 2. กำหนด Event Handler เมื่อได้รับข้อมูล<br>xhr.onload = function() {<br>    // ข้อมูลทั้งหมดถูกรับมาแล้ว (กรณีที่เซิร์ฟเวอร์ปิด Stream)<br>    console.log('Stream Complete:', this.responseText);<br>    // นำข้อมูลสุดท้ายไปแสดงผล<br>    document.getElementById('results').innerHTML = this.responseText;<br>};<br><br>// 3. กำหนด Event Handler เมื่อได้รับข้อมูลเป็นชิ้น (Chunk) - สำคัญที่สุด<br>xhr.onprogress = function(event) {<br>    if (event.lengthComputable) {<br>        const loaded = event.loaded; // ขนาดข้อมูลที่โหลดมาแล้ว<br>        const total = event.total; // ขนาดรวม<br>        console.log('Progress:', Math.round((loaded / total) * 100) + '%');<br>        // ในความเป็นจริง: ต้องมีการ Parse ข้อมูลที่เข้ามาใน Chunk นี้และอัปเดต DOM<br>        // เช่น: displayChunk(event.data);<br>    }<br>};<br><br>// 4. เปิดการเชื่อมต่อและส่งคำขอ<br>xhr.open('GET', '/api/stream-data', true);<br>xhr.send();
“>

การใช้ onprogress คือกุญแจสำคัญที่ทำให้ Ajax สามารถรับข้อมูลแบบ Stream ได้อย่างแท้จริง ทำให้ UI ไม่ค้างและผู้ใช้เห็นการอัปเดตข้อมูลแบบ Real-time

✨ บทสรุปสำหรับ Senior Architect

“>

การทำ Streaming Data ไม่ใช่แค่การลดเวลาการโหลด แต่เป็นการปรับปรุง User Experience (UX) และ System Performance ในการจัดการ I/O ที่มีขนาดใหญ่ การออกแบบระบบที่ถูกต้องต้องเริ่มตั้งแต่การจัดการทรัพยากรที่ PostgreSQL (ใช้ Cursors) การส่งข้อมูลที่ Backend (ใช้ Streaming Response) และการรับข้อมูลที่ Client (ใช้ XHR onprogress) เพื่อให้มั่นใจว่าข้อมูลจะถูกประมวลผลและแสดงผลอย่างต่อเนื่อง ไม่ใช่การรอจนกว่างานทั้งหมดจะเสร็จสมบูรณ์

Exit mobile version