ภาพหน้าจอที่แสดงมาจากส่วนปัญหาจําลองของบทความไม่ใช่ปัญหารหัสเดิมเนื่องจากความกังวลเกี่ยวกับความเป็นส่วนตัว ภาพหน้าจอที่แสดงมาจากส่วนปัญหาจําลองของบทความไม่ใช่ปัญหารหัสเดิมเนื่องจากความกังวลเกี่ยวกับความเป็นส่วนตัว ️ตารางเนื้อหา การตั้งค่า ปัญหา: Page Freeze on Input ความพยายาม Debugging ที่ล้มเหลว The Breakthrough: Pause Script การดําเนินการ The Root Cause: A Loop That Never Ends การจําลองการแช่แข็ง (ลองตัวเอง) สิ่งที่ฉันได้เรียนรู้ ความคิดโบนัส: Debugging Memory Leaks ช่วงเวลา การตั้งค่า ปั๊มนี้ปรากฏใน a โครงการ React + TypeScript + Redux + RxJS รูปแบบมีฟิลด์ตัวเลขเดียว . เมื่ออัปเดตมันเปิดตัว a (สร้างโดยใช้ ) เพื่อคํานวณ สถาบันซิงค์ข้อความ quantity Redux selector reselect Total cost ทุกอย่างดูดีบน ด้านข้าง Buy แต่เปลี่ยนไปยัง หน้าที่ทําให้เกิดสิ่งที่แปลกประหลาด: หน้าแช่แข็งทันทีเมื่อเข้าถึงแม้กระทั่ง . Sell 1 ปัญหา: Page Freeze on Input เมื่อพิมพ์ในฟิลด์ปริมาณ: The UI froze completely The browser tab became unresponsive The in Chrome Performance Monitor. (Sometimes, the JS heap size also keeps increasing) CPU usage 100% นี่ไม่ใช่การ render “ช้า” โดยทั่วไป มันเป็น . เต็ม hang Chrome ในที่สุดก็แสดงกล่องโต้ตอบ "Page Unresponsive" และฉันต้องฆ่าแท็บ ความพยายาม Debugging ที่ล้มเหลว วิธีการ debugging ปกติไม่ได้ช่วย: Attempt Result console.log Never printed anything debugger; Too slow or never triggered React DevTools Profiler Froze with the app Chrome Performance Profiler Couldn’t finish recording Removing components Still froze, even with just the input console.log ไม่เคยพิมพ์อะไร debugger; ยานเกินไปหรือไม่เคยเปิดตัว โปรไฟล์ React DevTools Froze กับ app โปรไฟล์ประสิทธิภาพของ Chrome ไม่สามารถเสร็จสิ้นการบันทึก การกําจัดส่วนประกอบ ยังคงแช่แข็งแม้จะมีเพียงอินพุต ปัญหาต้องเป็น a ขั้นตอนที่ไม่มีที่สิ้นสุด แต่ที่ไหน loop or recursive render The Breakthrough: Pause Script การดําเนินการ จากนั้นฉันมาถึงการตระหนักว่า: ถ้า JavaScript เก็บยังคงเติบโต . JavaScript is still running ดังนั้นฉันเปิด และใช้เครื่องประดับที่ซ่อนอยู่: Chrome DevTools → Sources tab Pause Script Execution (⏸️) แต่น่าเสียดายที่ฉันไม่เห็นคําอธิบายของคุณลักษณะนี้แม้ในเอกสาร Chrome DevTools อย่างเป็นทางการ: https://developer.chrome.com/docs/devtools/javascript/breakpoint แต่น่าเสียดายที่ฉันไม่เห็นคําอธิบายของคุณลักษณะนี้แม้ในเอกสาร Chrome DevTools อย่างเป็นทางการ: https://developer.chrome.com/docs/devtools/javascript/breakpoint https://developer.chrome.com/docs/devtools/javascript/breakpoint ขั้นตอน : Open Chrome DevTools first! You won’t be able to open them during the freeze. Reproduce the freeze (enter quantity). When the tab hangs, open . DevTools → Sources tab Click the icon (top-right). ⏸️ Pause Chrome freezes JS execution . at that exact line Scroll down on the right panel & check the panel to trace which functions are currently executing. Call Stack Scroll through the parent calls to reveal how the function chain started. You can even click on the parent calls to see their invoked line! The Root Cause: A Loop That Never Ends สแต็คที่หยุดชะงักแสดงให้เห็นว่ามีโซ่ของฟังก์ชั่น 8 + เริ่มต้นด้วย handler และสิ้นสุดภายใน a ใช้โดย A . onChange utility function Redux Reselect selector นี่คือผู้รับผิด: let a = 0; const size = props.size; // expected number, got string while (a < size) { // do something } กลายเป็น มาจากค่าอินพุตโดยตรง: a เช่น . props.size string "5" เนื่องจากข้อผิดพลาดของการบังคับใช้ JS การเปรียบเทียบวงจรไม่สามารถออกได้ภายใต้เงื่อนไขบางอย่างทําให้เกิดวงจรที่ไม่มีที่สิ้นสุดและแช่แข็งลวดทั้งหมด การแก้ไขมันเป็นเรื่องง่ายเช่นการแปลงค่าเป็นตัวเลขก่อนที่จะใช้: const size = Number(props.size); ทันทีหน้าแช่แข็งหายไป การจําลองการแช่แข็ง (ลองตัวเอง) คุณสามารถสร้างใหม่ข้อผิดพลาดที่แน่นอนนี้และลองเทคนิคการแก้ไขปัญหาด้วยตัวเองโดยไปที่ codesandbox นี้ หรือเรียกใช้รหัสด้านล่างในรหัสใหม่ แต่บันทึกงานของคุณก่อนเพราะนี้ วางเบราว์เซอร์ของคุณ เชื่อมโยง Create React App, ทารก เชื่อมโยง import { useState } from "react"; export default function App() { const [quantity, setQuantity] = useState(""); const handleChange = (e) => { const value = e.target.value; setQuantity(value); const end = Date.now() + 145000; let a = 0; // ❌ Intentional infinite loop while (Date.now() < end) { // Busy-wait a++; } console.log("Done!"); // never reached }; return ( <div style={{ padding: 20 }}> <h2>🧊 Simulate a Page Freeze</h2> <input type="text" placeholder="Enter quantity" value={quantity} onChange={handleChange} /> <p>Type any number and watch Chrome suffer.</p> </div> ); } ขั้นตอนในการทําซ้ํา เปิดรหัสนี้ใน codesandbox ด้านบนหรือในท้องถิ่น ป้อนหมายเลขใด ๆ ในอินพุต ดูแท็บแช่แข็ง Solid เปิด Chrome DevTools → แท็บแหล่งข้อมูล → ️ ปิดการทํางานของสคริปต์ ตรวจสอบวงจรที่ไม่มีที่สิ้นสุดภายใน HandChange ใน Stack Call สิ่งที่ฉันได้เรียนรู้ เมื่อไม่มีอะไรทํางาน: การดําเนินการสคริปต์หยุดเป็นลูกบอลเงิน ล็อคที่ไม่มีที่สิ้นสุดสามารถซ่อนอยู่ภายในตัวเลือกตัวลดหรือไฟล์ยูทิลิตี้ห่างจากอินเตอร์เฟซอินเตอร์เฟซ เสมอ sanitize และตรวจสอบการป้อนข้อมูลผู้ใช้ก่อนคํานวณ ในขณะที่ล้อเป็นเครื่องมือที่คมชัด: เงื่อนไขที่ไม่ถูกต้องหนึ่งครั้งและแอปของคุณกลายเป็น CPU Toaster ความคิดโบนัส: Debugging Memory Leaks เทคนิคเดียวกันสามารถช่วยติดตามช้า →กรณีที่ JS เคลือบจะเพิ่มขึ้นค่อยๆ memory leaks การหยุดการทํางานของสคริปต์ในช่วงเวลาว่างเปล่าอาจแสดงให้เห็นว่ากระบวนการพื้นหลังหรือการสมัครใช้งานยังคงทํางานอย่างไม่จําเป็น แต่นี่คือการทดลองสําหรับบทความอื่น 😉