ข้ามไปเนื้อหาหลัก

React และ IndexedDB: ตรวจสอบ CSV 10,000 แถวใน 20ms

วิธีทำความสะอาดข้อมูล CSV ขนาด 10,000 แถวด้วย TypeScript บนฝั่งเบราว์เซอร์ใน 20.11 มิลลิวินาที โดยไม่กระทบเซิร์ฟเวอร์และใช้ IndexedDB เก็บฉบับร่าง

เรียบเรียงโดย AI
Inewgen
08 Nov 2026ที่มา: Dev.to4 นาทีอ่าน (0 ครั้ง)
แชร์
React และ IndexedDB: ตรวจสอบ CSV 10,000 แถวใน 20ms

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง

ขนาดตัวอักษร
  • ตรวจสอบ CSV 10,000 แถว (40,000 เซลล์) ภายในเวลาเพียง 20.11 มิลลิวินาทีบนฝั่งเบราว์เซอร์
  • ใช้ Set แทน Array.prototype.some() เพื่อป้องกันปัญหาความเร็วตกจากการตรวจสอบซ้ำซ้อน
  • ใช้เฮลเปอร์ IndexedDB ขนาด 45 บรรทัดเก็บข้อมูลร่างขนาดใหญ่โดยไม่ชนข้อจำกัด 5 MB ของ localStorage
  • เน้นย้ำความสำคัญของการใช้ RFC-4180 ป้องกันปัญหาคอมมาในเครื่องหมายคำพูดดันคอลัมน์เคลื่อน

เวลาที่เราเห็นผู้ใช้งานอัปโหลดไฟล์ CSV ใบแจ้งหนี้ขนาด 10,000 แถวผ่านอินเทอร์เน็ตที่สัญญาณไม่ค่อยดีบนเว็บแอปพลิเคชันทั่วไป มักจะพบปัญหาแถบความคืบหน้าวิ่งไปถึงร้อยเปอร์เซ็นต์อย่างช้าๆ แล้วถูกดีดกลับมาพร้อมข้อความสีแดงแจ้งเตือนข้อผิดพลาด 400 Bad Request ระบุว่ามีจำนวนเงินไม่ถูกต้องที่แถว 7,500 ส่งผลให้ผู้ใช้ต้องแก้ไขแถวดังกล่าวแล้วอัปโหลดไฟล์ทั้งหมดใหม่อีกรอบ จนกว่าจะเจอข้อผิดพลาดจุดอื่นถัดไป

ยิ่งไปกว่านั้น หากการเชื่อมต่ออินเทอร์เน็ตเกิดหลุดขณะที่ผู้ใช้กำลังแก้ไขข้อมูลภายในยูสเซอร์อินเทอร์เฟซและเผลอรีเฟรชหน้าจอ ปัญหามักจะแย่ลงไปอีก เนื่องจากแอปพลิเคชันจำนวนมากพยายามเก็บข้อมูลฉบับร่างไว้ใน localStorage โดยลืมไปว่าเบราว์เซอร์จำกัดขนาด localStorage ไว้ที่ประมาณ 5 เมกะไบต์และบล็อกเทรดหลักแบบซิงโครนัส ส่งผลให้เกิดข้อผิดพลาด QuotaExceededError ในช่วงเวลาที่ผู้ใช้งานต้องการข้อมูลสำรองมากที่สุด

ปัญหานี้สามารถแก้ไขได้บนฝั่งฟรอนต์เอนด์โดยไม่ต้องดึงไลบรารีตรวจสอบความถูกต้องขนาด 200 กิโลไบต์เข้ามาเพิ่ม โดยในรีโพสทอรีประกอบ (github.com/endlessfountain/react-offline-sheet-guard) นักพัฒนาได้สร้างระบบตรวจสอบล่วงหน้าด้วย TypeScript ขนาดเล็กที่สามารถตรวจสอบ CSV จำนวน 10,000 แถวหรือคิดเป็น 40,000 เซลล์ภายในเวลา 20.11 มิลลิวินาทีก่อนที่ข้อมูลไบต์เดียวจะวิ่งไปถึงเน็ตเวิร์ก ควบคู่ไปกับเฮลเปอร์ IndexedDB ขนาด 45 บรรทัดที่ช่วยให้ข้อมูลร่างขนาดหลายเมกะไบต์ปลอดภัยจากการรีเฟรชหน้าจอออฟไลน์

การตรวจสอบว่าอีเมลถูกต้องหรือไม่หรือจำนวนที่นั่งเป็นจำนวนเต็มนั้นใช้ต้นทุนต่ำ แต่จุดที่ทำลายประสิทธิภาพของเบราว์เซอร์เงียบๆ บนชีตข้อมูลขนาด 10,000 แถวคือการตรวจจับรหัสซ้ำ (Duplicate ID Detection)

10,000แถว CSV
20.11msเวลาประมวลผล
418.8 KBข้อมูลที่ประหยัดได้

เมื่อนักพัฒนาเขียนโค้ดตรวจสอบฝั่งไคลเอนต์อย่างรวดเร็ว มักจะเรียกใช้งาน Array.prototype.some() ภายในลูปแถว ซึ่งจะทำให้เกิดการเปรียบเทียบสตริงมากถึง 50 ล้านครั้ง ส่งผลให้หน้าจอค้างเกือบหนึ่งวินาทีบนแล็ปท็อประดับกลาง การเปลี่ยนจากการสแกนอาร์เรย์เป็นการใช้ Set ช่วยรักษาความเร็วในการตรวจจับรหัสซ้ำให้อยู่ในระดับ O(1) ต่อแถวตามที่ระบุไว้ใน src/engine/sheetValidator.ts

code editor programming screen laptop no logo

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง

การประมวลผลข้อมูลฝั่งไคลเอนต์ด้วย TypeScript และ IndexedDB ก่อนส่งขึ้นเซิร์ฟเวอร์ถือเป็นแนวทางปฏิบัติที่ช่วยยกระดับประสบการณ์ผู้ใช้งานอย่างมีนัยสำคัญ เนื่องจากลดภาระของเครือข่ายและเซิร์ฟเวอร์ backend ได้พร้อมกัน อย่างไรก็ตาม นักพัฒนาพึงระลึกเสมอว่าการตรวจสอบฝั่งฟรอนต์เอนด์เป็นเรื่องของ UX และแบนด์วิดท์เท่านั้น ไม่ใช่เกราะป้องกันด้านความปลอดภัย เนื่องจากผู้ไม่หวังสามารถส่งเพย์โหลดที่ไม่ถูกต้องตรงไปยัง API ผ่าน curl ได้เสมอ จึงจำเป็นต้องมีกฎการตรวจสอบเดียวกันบนฝั่งเซิร์ฟเวอร์ด้วยเช่นกัน

จากการรันคำสั่ง npm test ในรีโพสทอรี ระบบจะสร้างไฟล์ CSV ขนาด 10,000 แถวที่มีขนาด 418.8 กิโลไบต์ พร้อมฝังข้อผิดพลาดไว้ 4 จุด ได้แก่ รหัสซ้ำที่แถว 50, อีเมลไม่ถูกต้องที่แถว 500, ข้อความราคามีเครื่องหมายดอลลาร์ "$1200" ที่แถว 2,500 และจำนวนที่นั่ง 3.5 ที่แถว 7,500

ไม่อยากพลาดข่าวใหม่?

สมัครรับสรุปข่าวสารใหม่ทางอีเมล ไม่บ่อยจนรำคาญ

โฆษณา

"20 milliseconds is barely over a single 60Hz browser frame (16.6ms), and catching those four typos upfront avoids shipping 418.8 KB over the wire on a doomed POST request."

endlessfountain

เวลา 20 มิลลิวินัตินี้ช้ากว่าเฟรมเบราว์เซอร์ 60Hz เพียงเล็กน้อยเท่านั้น (16.6 มิลลิวินาที) และการจับข้อผิดพลาดทั้งสี่จุดล่วงหน้าช่วยหลีกเลี่ยงการส่งข้อมูลขนาด 418.8 กิโลไบต์ผ่านเครือข่ายไปยังคำขอ POST ที่ล้มเหลวตั้งแต่ต้น

สำหรับการเก็บข้อมูลร่างขนาดหลายเมกะไบต์ใน IndexedDB โดยไม่ต้องติดตั้งแพ็กเกจเพิ่มเติม เนื่องจาก IndexedDB แบบดั้งเดิมมี API Callback จากปี 2012 ที่ซับซ้อน ทำให้ผู้คนหันไปใช้ไลบรารีห่อหุ้มหรือพึ่งพา localStorage แทน แต่ในความเป็นจริง หากต้องการแค่บันทึกและกู้คืนร่างการอัปโหลดตามคีย์ การห่อหุ้มคำสั่ง open, put และ get ด้วย Promises จะใช้โค้ดประมาณ 35 บรรทัดใน src/storage/draftDb.ts

ที่มา: Dev.to

ความคิดเห็น

แสดงความคิดเห็น
0/2000

พบข้อมูลผิดพลาดในบทความนี้? แจ้งปัญหาบทความนี้