52 KiB
สร้างแอปธนาคาร ตอนที่ 4: แนวคิดการจัดการสถานะ
แบบทดสอบก่อนเรียน
บทนำ
การจัดการสถานะเปรียบเสมือนระบบนำทางบนยาน Voyager – เมื่อทุกอย่างทำงานได้อย่างราบรื่น คุณแทบจะไม่รู้สึกถึงการมีอยู่ของมัน แต่เมื่อเกิดปัญหา มันจะกลายเป็นตัวแปรสำคัญที่ทำให้ยานไปถึงอวกาศระหว่างดวงดาวหรือหลงทางในอวกาศ ในการพัฒนาเว็บ สถานะหมายถึงทุกสิ่งที่แอปพลิเคชันของคุณต้องจดจำ เช่น สถานะการเข้าสู่ระบบของผู้ใช้ ข้อมูลในฟอร์ม ประวัติการนำทาง และสถานะชั่วคราวของอินเทอร์เฟซ
เมื่อแอปธนาคารของคุณพัฒนาจากฟอร์มเข้าสู่ระบบแบบง่าย ๆ ไปเป็นแอปพลิเคชันที่ซับซ้อนมากขึ้น คุณอาจพบกับความท้าทายทั่วไป เช่น การรีเฟรชหน้าแล้วผู้ใช้ถูกออกจากระบบโดยไม่คาดคิด การปิดเบราว์เซอร์แล้วความคืบหน้าทั้งหมดหายไป หรือการแก้ไขปัญหาโดยต้องค้นหาผ่านฟังก์ชันหลาย ๆ ตัวที่แก้ไขข้อมูลเดียวกันในวิธีที่ต่างกัน
นี่ไม่ใช่สัญญาณของการเขียนโค้ดที่ไม่ดี – แต่เป็นความเจ็บปวดที่เกิดขึ้นตามธรรมชาติเมื่อแอปพลิเคชันมีความซับซ้อนถึงระดับหนึ่ง นักพัฒนาทุกคนต้องเผชิญกับความท้าทายเหล่านี้เมื่อแอปพลิเคชันเปลี่ยนจาก "การพิสูจน์แนวคิด" ไปเป็น "พร้อมใช้งานจริง"
ในบทเรียนนี้ เราจะนำระบบการจัดการสถานะที่เป็นศูนย์กลางมาใช้เพื่อเปลี่ยนแอปธนาคารของคุณให้เป็นแอปพลิเคชันที่เชื่อถือได้และเป็นมืออาชีพ คุณจะได้เรียนรู้วิธีจัดการการไหลของข้อมูลอย่างคาดการณ์ได้ รักษาสถานะการเข้าสู่ระบบของผู้ใช้อย่างเหมาะสม และสร้างประสบการณ์ผู้ใช้ที่ราบรื่นซึ่งแอปพลิเคชันเว็บสมัยใหม่ต้องการ
ความรู้พื้นฐานที่ต้องมี
ก่อนที่จะดำดิ่งสู่แนวคิดการจัดการสถานะ คุณต้องตั้งค่าพื้นฐานการพัฒนาและมีโครงสร้างแอปธนาคารของคุณพร้อม บทเรียนนี้สร้างขึ้นจากแนวคิดและโค้ดจากส่วนก่อนหน้าของซีรีส์นี้โดยตรง
การตั้งค่าที่จำเป็น:
- ทำบทเรียน การดึงข้อมูล ให้เสร็จสมบูรณ์ - แอปของคุณควรโหลดและแสดงข้อมูลบัญชีได้สำเร็จ
- ติดตั้ง Node.js บนระบบของคุณเพื่อรัน API ฝั่งเซิร์ฟเวอร์
- เริ่มต้น API เซิร์ฟเวอร์ ในเครื่องเพื่อจัดการการดำเนินการข้อมูลบัญชี
การทดสอบสภาพแวดล้อมของคุณ:
ตรวจสอบว่า API เซิร์ฟเวอร์ของคุณทำงานได้อย่างถูกต้องโดยการรันคำสั่งนี้ในเทอร์มินัล:
curl http://localhost:5000/api
# -> should return "Bank API v1.0.0" as a result
สิ่งที่คำสั่งนี้ทำ:
- ส่งคำขอ GET ไปยัง API เซิร์ฟเวอร์ในเครื่องของคุณ
- ทดสอบการเชื่อมต่อและตรวจสอบว่าเซิร์ฟเวอร์ตอบสนอง
- ส่งคืนข้อมูลเวอร์ชัน API หากทุกอย่างทำงานได้อย่างถูกต้อง
การวินิจฉัยปัญหาสถานะปัจจุบัน
เหมือนกับ Sherlock Holmes ที่ตรวจสอบสถานที่เกิดเหตุ เราต้องเข้าใจว่าเกิดอะไรขึ้นในโครงสร้างปัจจุบันของเราก่อนที่เราจะสามารถแก้ปัญหาการสูญเสียสถานะผู้ใช้ได้
มาทำการทดลองง่าย ๆ ที่เผยให้เห็นความท้าทายในการจัดการสถานะ:
🧪 ลองทดสอบการวินิจฉัยนี้:
- เข้าสู่ระบบแอปธนาคารของคุณและไปที่แดชบอร์ด
- รีเฟรชหน้าเบราว์เซอร์
- สังเกตว่าเกิดอะไรขึ้นกับสถานะการเข้าสู่ระบบของคุณ
หากคุณถูกเปลี่ยนกลับไปที่หน้าจอเข้าสู่ระบบ คุณได้ค้นพบปัญหาคลาสสิกของการคงสถานะแล้ว พฤติกรรมนี้เกิดขึ้นเพราะการใช้งานปัจจุบันของเราจัดเก็บข้อมูลผู้ใช้ในตัวแปร JavaScript ที่รีเซ็ตทุกครั้งที่โหลดหน้าใหม่
ปัญหาการใช้งานปัจจุบัน:
ตัวแปร account แบบง่ายจาก บทเรียนก่อนหน้า สร้างปัญหาสำคัญสามประการที่ส่งผลต่อทั้งประสบการณ์ผู้ใช้และการดูแลรักษาโค้ด:
| ปัญหา | สาเหตุทางเทคนิค | ผลกระทบต่อผู้ใช้ |
|---|---|---|
| การสูญเสียเซสชัน | การรีเฟรชหน้าล้างตัวแปร JavaScript | ผู้ใช้ต้องเข้าสู่ระบบใหม่บ่อยครั้ง |
| การอัปเดตกระจัดกระจาย | ฟังก์ชันหลายตัวแก้ไขสถานะโดยตรง | การแก้ไขข้อบกพร่องยากขึ้นเรื่อย ๆ |
| การล้างข้อมูลไม่สมบูรณ์ | การออกจากระบบไม่ล้างการอ้างอิงสถานะทั้งหมด | ความกังวลด้านความปลอดภัยและความเป็นส่วนตัว |
ความท้าทายด้านสถาปัตยกรรม:
เหมือนกับการออกแบบห้องของ Titanic ที่ดูแข็งแกร่งจนกระทั่งห้องหลายห้องถูกน้ำท่วมพร้อมกัน การแก้ไขปัญหาเหล่านี้ทีละปัญหาไม่สามารถแก้ไขปัญหาสถาปัตยกรรมพื้นฐานได้ เราต้องการโซลูชันการจัดการสถานะที่ครอบคลุม
💡 เรากำลังพยายามทำอะไรที่นี่?
การจัดการสถานะ เป็นเรื่องของการแก้ปริศนาสองข้อพื้นฐาน:
- ข้อมูลของฉันอยู่ที่ไหน?: การติดตามว่ามีข้อมูลอะไรและมาจากไหน
- ทุกคนเข้าใจตรงกันหรือไม่?: การทำให้สิ่งที่ผู้ใช้เห็นตรงกับสิ่งที่เกิดขึ้นจริง
แผนการของเรา:
แทนที่จะไล่ตามปัญหา เราจะสร้างระบบ การจัดการสถานะที่เป็นศูนย์กลาง คิดว่ามันเหมือนกับการมีคนที่จัดระเบียบได้ดีคนหนึ่งที่ดูแลเรื่องสำคัญทั้งหมด:
การทำความเข้าใจการไหลของข้อมูลนี้:
- รวมศูนย์สถานะของแอปพลิเคชันทั้งหมดในที่เดียว
- กำหนดเส้นทางการเปลี่ยนแปลงสถานะทั้งหมดผ่านฟังก์ชันที่ควบคุม
- รับรองว่า UI ยังคงสอดคล้องกับสถานะปัจจุบัน
- ให้รูปแบบที่ชัดเจนและคาดการณ์ได้สำหรับการจัดการข้อมูล
💡 ข้อมูลเชิงลึกระดับมืออาชีพ: บทเรียนนี้มุ่งเน้นไปที่แนวคิดพื้นฐาน สำหรับแอปพลิเคชันที่ซับซ้อนมากขึ้น ไลบรารีอย่าง Redux มีฟีเจอร์การจัดการสถานะที่ก้าวหน้ามากขึ้น การเข้าใจหลักการพื้นฐานเหล่านี้จะช่วยให้คุณเชี่ยวชาญไลบรารีการจัดการสถานะใด ๆ
⚠️ หัวข้อขั้นสูง: เราจะไม่ครอบคลุมการอัปเดต UI อัตโนมัติที่เกิดจากการเปลี่ยนแปลงสถานะ เนื่องจากเกี่ยวข้องกับแนวคิด การเขียนโปรแกรมเชิงปฏิกิริยา ถือว่าเป็นขั้นตอนต่อไปที่ยอดเยี่ยมสำหรับการเรียนรู้ของคุณ!
งาน: รวมโครงสร้างสถานะ
มาเริ่มเปลี่ยนการจัดการสถานะที่กระจัดกระจายของเราให้เป็นระบบรวมศูนย์กัน ขั้นตอนแรกนี้เป็นการสร้างรากฐานสำหรับการปรับปรุงทั้งหมดที่จะตามมา
ขั้นตอนที่ 1: สร้างวัตถุสถานะรวมศูนย์
แทนที่การประกาศ account แบบง่าย:
let account = null;
ด้วยวัตถุสถานะที่มีโครงสร้าง:
let state = {
account: null
};
เหตุผลที่การเปลี่ยนแปลงนี้สำคัญ:
- รวมศูนย์ข้อมูลแอปพลิเคชันทั้งหมดในที่เดียว
- เตรียมโครงสร้างสำหรับการเพิ่มคุณสมบัติสถานะเพิ่มเติมในภายหลัง
- สร้างขอบเขตที่ชัดเจนระหว่างสถานะและตัวแปรอื่น ๆ
- สร้างรูปแบบที่สามารถขยายได้เมื่อแอปของคุณเติบโต
ขั้นตอนที่ 2: อัปเดตรูปแบบการเข้าถึงสถานะ
อัปเดตฟังก์ชันของคุณให้ใช้โครงสร้างสถานะใหม่:
ในฟังก์ชัน register() และ login(), แทนที่:
account = ...
ด้วย:
state.account = ...
ในฟังก์ชัน updateDashboard(), เพิ่มบรรทัดนี้ที่ด้านบน:
const account = state.account;
สิ่งที่การอัปเดตเหล่านี้ทำสำเร็จ:
- รักษาฟังก์ชันการทำงานที่มีอยู่ในขณะที่ปรับปรุงโครงสร้าง
- เตรียมโค้ดของคุณสำหรับการจัดการสถานะที่ซับซ้อนมากขึ้น
- สร้างรูปแบบที่สอดคล้องกันสำหรับการเข้าถึงข้อมูลสถานะ
- สร้างรากฐานสำหรับการอัปเดตสถานะรวมศูนย์
💡 หมายเหตุ: การปรับโครงสร้างนี้ไม่ได้แก้ปัญหาของเราในทันที แต่สร้างรากฐานที่จำเป็นสำหรับการปรับปรุงที่ทรงพลังที่จะตามมา!
การดำเนินการอัปเดตสถานะที่ควบคุม
เมื่อสถานะของเรารวมศูนย์แล้ว ขั้นตอนต่อไปคือการสร้างกลไกที่ควบคุมสำหรับการแก้ไขข้อมูล วิธีนี้ช่วยให้การเปลี่ยนแปลงสถานะสามารถคาดการณ์ได้และแก้ไขข้อบกพร่องได้ง่ายขึ้น
หลักการสำคัญคล้ายกับการควบคุมการจราจรทางอากาศ: แทนที่จะอนุญาตให้ฟังก์ชันหลายตัวแก้ไขสถานะอย่างอิสระ เราจะส่งการเปลี่ยนแปลงทั้งหมดผ่านฟังก์ชันที่ควบคุมเดียว รูปแบบนี้ให้การดูแลที่ชัดเจนว่าเมื่อใดและอย่างไรที่ข้อมูลเปลี่ยนแปลง
การจัดการสถานะที่ไม่เปลี่ยนแปลง:
เราจะถือว่าวัตถุ state ของเราเป็น ไม่เปลี่ยนแปลง หมายความว่าเราจะไม่แก้ไขมันโดยตรง แต่ละการเปลี่ยนแปลงจะสร้างวัตถุสถานะใหม่พร้อมข้อมูลที่อัปเดต
แม้ว่าวิธีนี้อาจดูเหมือนไม่มีประสิทธิภาพในตอนแรกเมื่อเทียบกับการแก้ไขโดยตรง แต่มันให้ข้อดีที่สำคัญสำหรับการแก้ไขข้อบกพร่อง การทดสอบ และการรักษาความสามารถในการคาดการณ์ของแอปพลิเคชัน
ประโยชน์ของการจัดการสถานะที่ไม่เปลี่ยนแปลง:
| ประโยชน์ | คำอธิบาย | ผลกระทบ |
|---|---|---|
| ความสามารถในการคาดการณ์ | การเปลี่ยนแปลงเกิดขึ้นผ่านฟังก์ชันที่ควบคุมเท่านั้น | แก้ไขข้อบกพร่องและทดสอบได้ง่ายขึ้น |
| การติดตามประวัติ | การเปลี่ยนแปลงสถานะแต่ละครั้งสร้างวัตถุใหม่ | รองรับฟังก์ชันย้อนกลับ/ทำซ้ำ |
| ป้องกันผลกระทบข้างเคียง | ไม่มีการแก้ไขโดยไม่ได้ตั้งใจ | ป้องกันข้อบกพร่องที่ไม่คาดคิด |
| การปรับปรุงประสิทธิภาพ | ตรวจจับได้ง่ายเมื่อสถานะเปลี่ยนแปลงจริง | รองรับการอัปเดต UI อย่างมีประสิทธิภาพ |
การจัดการสถานะไม่เปลี่ยนแปลงใน JavaScript ด้วย Object.freeze():
JavaScript มี Object.freeze() เพื่อป้องกันการแก้ไขวัตถุ:
const immutableState = Object.freeze({ account: userData });
// Any attempt to modify immutableState will throw an error
การแยกย่อยสิ่งที่เกิดขึ้นที่นี่:
- ป้องกันการกำหนดค่าหรือการลบคุณสมบัติโดยตรง
- โยนข้อยกเว้นหากมีการพยายามแก้ไข
- รับรองว่าการเปลี่ยนแปลงสถานะต้องผ่านฟังก์ชันที่ควบคุม
- สร้างสัญญาที่ชัดเจนสำหรับวิธีการอัปเดตสถานะ
💡 เจาะลึก: เรียนรู้เกี่ยวกับความแตกต่างระหว่างวัตถุไม่เปลี่ยนแปลงแบบ ตื้น และ ลึก ใน เอกสาร MDN การเข้าใจความแตกต่างนี้เป็นสิ่งสำคัญสำหรับโครงสร้างสถานะที่ซับซ้อน
งาน
มาสร้างฟังก์ชัน updateState() ใหม่:
function updateState(property, newData) {
state = Object.freeze({
...state,
[property]: newData
});
}
ในฟังก์ชันนี้ เรากำลังสร้างวัตถุสถานะใหม่และคัดลอกข้อมูลจากสถานะก่อนหน้าด้วย ตัวดำเนินการกระจาย (...) จากนั้นเราจะเขียนทับคุณสมบัติเฉพาะของวัตถุสถานะด้วยข้อมูลใหม่โดยใช้ สัญลักษณ์วงเล็บ [property] สำหรับการกำหนดค่า สุดท้ายเราล็อควัตถุเพื่อป้องกันการแก้ไขโดยใช้ Object.freeze() ตอนนี้เรามีคุณสมบัติ account ที่จัดเก็บในสถานะเท่านั้น แต่ด้วยวิธีนี้คุณสามารถเพิ่มคุณสมบัติได้มากเท่าที่คุณต้องการในสถานะ
เราจะอัปเดตการเริ่มต้นสถานะเพื่อให้แน่ใจว่าสถานะเริ่มต้นถูกล็อคด้วย:
let state = Object.freeze({
account: null
});
หลังจากนั้น อัปเดตฟังก์ชัน register โดยแทนที่การกำหนดค่า state.account = result; ด้วย:
updateState('account', result);
ทำเช่นเดียวกันกับฟังก์ชัน login โดยแทนที่ state.account = data; ด้วย:
updateState('account', data);
เราจะใช้โอกาสนี้แก้ไขปัญหาข้อมูลบัญชีที่ไม่ได้ถูกล้างเมื่อผู้ใช้คลิก Logout
สร้างฟังก์ชันใหม่ logout():
function logout() {
updateState('account', null);
navigate('/login');
}
ใน updateDashboard(), แทนที่การเปลี่ยนเส้นทาง return navigate('/login'); ด้วย return logout();
ลองลงทะเบียนบัญชีใหม่ ออกจากระบบ และเข้าสู่ระบบอีกครั้งเพื่อตรวจสอบว่าทุกอย่างยังทำงานได้อย่างถูกต้อง
เคล็ดลับ: คุณสามารถดูการเปลี่ยนแปลงสถานะทั้งหมดได้โดยเพิ่ม
console.log(state)ที่ด้านล่างของupdateState()และเปิดคอนโซลในเครื่องมือพัฒนาเบราว์เซอร์ของคุณ
การดำเนินการคงข้อมูล
ปัญหาการสูญเสียเซสชันที่เราระบุไว้ก่อนหน้านี้ต้องการโซลูชันการคงข้อมูลที่รักษาสถานะผู้ใช้ในเซสชันเบราว์เซอร์ โซลูชันนี้เปลี่ยนแอปพลิเคชันของเราจากประสบการณ์ชั่วคราวไปเป็นเครื่องมือที่เชื่อถือได้และเป็นมืออาชีพ
ลองพิจารณาว่านาฬิกาอะตอมรักษาเวลาได้อย่างแม่นยำแม้ในช่วงที่ไฟฟ้าดับโดยการจัดเก็บสถานะสำคัญในหน่วยความจำที่ไม่ระเหย เช่นเดียวกัน แอปพลิเคชันเว็บต้องการกลไกการจัดเก็บที่คงอยู่เพื่อรักษาข้อมูลผู้ใช้ที่สำคัญในเซสชันเบราว์เซอร์และการรีเฟรชหน้า
คำถามเชิงกลยุทธ์สำหรับการคงข้อมูล:
ก่อนดำเนินการคงข้อมูล ให้พิจารณาปัจจัยสำคัญเหล่านี้:
| คำถาม | บริบทแ
💡 ตัวเลือกขั้นสูง: สำหรับแอปพลิเคชันออฟไลน์ที่ซับซ้อนและมีชุดข้อมูลขนาดใหญ่ ลองใช้
IndexedDBAPI ซึ่งเป็นฐานข้อมูลฝั่งไคลเอนต์ที่สมบูรณ์ แต่ต้องการการพัฒนาโค้ดที่ซับซ้อนมากขึ้น
งาน: การจัดการข้อมูลแบบถาวรด้วย localStorage
เราจะมาทำการจัดการข้อมูลแบบถาวรเพื่อให้ผู้ใช้ยังคงล็อกอินอยู่จนกว่าพวกเขาจะออกจากระบบอย่างชัดเจน โดยเราจะใช้ localStorage ในการเก็บข้อมูลบัญชีระหว่างการใช้งานเบราว์เซอร์
ขั้นตอนที่ 1: กำหนดการตั้งค่าการจัดเก็บข้อมูล
const storageKey = 'savedAccount';
สิ่งที่ค่าคงที่นี้ให้:
- สร้าง ตัวระบุที่สอดคล้องกันสำหรับข้อมูลที่จัดเก็บ
- ป้องกัน การพิมพ์ผิดในการอ้างอิงคีย์การจัดเก็บ
- ทำให้ การเปลี่ยนคีย์การจัดเก็บง่ายขึ้นเมื่อจำเป็น
- ปฏิบัติตาม หลักการที่ดีที่สุดสำหรับโค้ดที่ดูแลรักษาได้ง่าย
ขั้นตอนที่ 2: เพิ่มการจัดการข้อมูลแบบถาวรอัตโนมัติ
เพิ่มบรรทัดนี้ในตอนท้ายของฟังก์ชัน updateState():
localStorage.setItem(storageKey, JSON.stringify(state.account));
การอธิบายสิ่งที่เกิดขึ้น:
- แปลง ออบเจ็กต์บัญชีเป็นสตริง JSON เพื่อจัดเก็บ
- บันทึก ข้อมูลโดยใช้คีย์การจัดเก็บที่สอดคล้องกัน
- ดำเนินการ โดยอัตโนมัติเมื่อเกิดการเปลี่ยนแปลงสถานะ
- รับรอง ว่าข้อมูลที่จัดเก็บจะสอดคล้องกับสถานะปัจจุบันเสมอ
💡 ประโยชน์ด้านสถาปัตยกรรม: เนื่องจากเราได้รวมการอัปเดตสถานะทั้งหมดไว้ใน
updateState()การเพิ่มการจัดการข้อมูลแบบถาวรจึงใช้เพียงบรรทัดเดียว ซึ่งแสดงให้เห็นถึงพลังของการตัดสินใจด้านสถาปัตยกรรมที่ดี!
ขั้นตอนที่ 3: คืนค่าข้อมูลเมื่อแอปพลิเคชันโหลด
สร้างฟังก์ชันเริ่มต้นเพื่อคืนค่าข้อมูลที่บันทึกไว้:
function init() {
const savedAccount = localStorage.getItem(storageKey);
if (savedAccount) {
updateState('account', JSON.parse(savedAccount));
}
// Our previous initialization code
window.onpopstate = () => updateRoute();
updateRoute();
}
init();
การทำความเข้าใจกระบวนการเริ่มต้น:
- ดึง ข้อมูลบัญชีที่บันทึกไว้ก่อนหน้านี้จาก localStorage
- แปลง สตริง JSON กลับเป็นออบเจ็กต์ JavaScript
- อัปเดต สถานะโดยใช้ฟังก์ชันอัปเดตที่ควบคุม
- คืนค่า เซสชันของผู้ใช้อัตโนมัติเมื่อโหลดหน้า
- ดำเนินการ ก่อนการอัปเดตเส้นทางเพื่อให้แน่ใจว่าสถานะพร้อมใช้งาน
ขั้นตอนที่ 4: ปรับปรุงเส้นทางเริ่มต้น
อัปเดตเส้นทางเริ่มต้นเพื่อใช้ประโยชน์จากการจัดการข้อมูลแบบถาวร:
ใน updateRoute() ให้แทนที่:
// Replace: return navigate('/login');
return navigate('/dashboard');
เหตุผลที่การเปลี่ยนแปลงนี้สมเหตุสมผล:
- ใช้ประโยชน์ จากระบบการจัดการข้อมูลแบบถาวรใหม่อย่างมีประสิทธิภาพ
- อนุญาต ให้แดชบอร์ดจัดการการตรวจสอบสิทธิ์
- เปลี่ยนเส้นทาง ไปยังหน้าล็อกอินโดยอัตโนมัติหากไม่มีเซสชันที่บันทึกไว้
- สร้าง ประสบการณ์การใช้งานที่ราบรื่นยิ่งขึ้นสำหรับผู้ใช้
การทดสอบการใช้งานของคุณ:
- ล็อกอินเข้าสู่แอปธนาคารของคุณ
- รีเฟรชหน้าเบราว์เซอร์
- ตรวจสอบว่าคุณยังคงล็อกอินอยู่และอยู่ในหน้าแดชบอร์ด
- ปิดและเปิดเบราว์เซอร์ใหม่
- กลับไปยังแอปของคุณและยืนยันว่าคุณยังคงล็อกอินอยู่
🎉 ความสำเร็จปลดล็อก: คุณได้ทำการจัดการสถานะแบบถาวรสำเร็จแล้ว! แอปของคุณตอนนี้ทำงานเหมือนแอปพลิเคชันเว็บระดับมืออาชีพ
การปรับสมดุลระหว่างการจัดการข้อมูลแบบถาวรกับความสดใหม่ของข้อมูล
ระบบการจัดการข้อมูลแบบถาวรของเราสามารถรักษาเซสชันของผู้ใช้ได้สำเร็จ แต่ก็สร้างความท้าทายใหม่: ข้อมูลที่ล้าสมัย เมื่อผู้ใช้หรือแอปพลิเคชันหลายตัวแก้ไขข้อมูลเซิร์ฟเวอร์เดียวกัน ข้อมูลที่แคชไว้ในเครื่องอาจไม่ทันสมัย
สถานการณ์นี้คล้ายกับนักเดินเรือไวกิ้งที่ใช้ทั้งแผนที่ดาวที่บันทึกไว้และการสังเกตการณ์ดาวปัจจุบัน แผนที่ให้ความสม่ำเสมอ แต่พวกเขาต้องการการสังเกตการณ์ใหม่เพื่อปรับตัวให้เข้ากับสภาพที่เปลี่ยนแปลง เช่นเดียวกัน แอปพลิเคชันของเราต้องการทั้งสถานะผู้ใช้ที่ถาวรและข้อมูลเซิร์ฟเวอร์ที่สดใหม่
🧪 การค้นพบปัญหาความสดใหม่ของข้อมูล:
- ล็อกอินเข้าสู่แดชบอร์ดโดยใช้บัญชี
test - รันคำสั่งนี้ในเทอร์มินัลเพื่อจำลองการทำธุรกรรมจากแหล่งอื่น:
curl --request POST \
--header "Content-Type: application/json" \
--data "{ \"date\": \"2020-07-24\", \"object\": \"Bought book\", \"amount\": -20 }" \
http://localhost:5000/api/accounts/test/transactions
- รีเฟรชหน้าแดชบอร์ดในเบราว์เซอร์
- สังเกตว่าคุณเห็นธุรกรรมใหม่หรือไม่
สิ่งที่การทดสอบนี้แสดงให้เห็น:
- แสดง ว่า localStorage อาจกลายเป็น "ล้าสมัย" (ไม่ทันสมัย)
- จำลอง สถานการณ์จริงที่ข้อมูลเปลี่ยนแปลงนอกแอปของคุณ
- เผย ความตึงเครียดระหว่างการจัดการข้อมูลแบบถาวรและความสดใหม่ของข้อมูล
ความท้าทายของข้อมูลล้าสมัย:
| ปัญหา | สาเหตุ | ผลกระทบต่อผู้ใช้ |
|---|---|---|
| ข้อมูลล้าสมัย | localStorage ไม่หมดอายุโดยอัตโนมัติ | ผู้ใช้เห็นข้อมูลที่ไม่ทันสมัย |
| การเปลี่ยนแปลงเซิร์ฟเวอร์ | แอป/ผู้ใช้อื่นแก้ไขข้อมูลเดียวกัน | มุมมองที่ไม่สอดคล้องกันระหว่างแพลตฟอร์ม |
| แคช vs. ความเป็นจริง | แคชในเครื่องไม่ตรงกับสถานะเซิร์ฟเวอร์ | ประสบการณ์ผู้ใช้ที่ไม่ดีและความสับสน |
กลยุทธ์การแก้ปัญหา:
เราจะใช้รูปแบบ "รีเฟรชเมื่อโหลด" ที่สมดุลระหว่างข้อดีของการจัดการข้อมูลแบบถาวรกับความต้องการข้อมูลที่สดใหม่ วิธีนี้จะช่วยรักษาประสบการณ์การใช้งานที่ราบรื่นในขณะที่รับรองความถูกต้องของข้อมูล
งาน: การสร้างระบบรีเฟรชข้อมูล
เราจะสร้างระบบที่ดึงข้อมูลใหม่จากเซิร์ฟเวอร์โดยอัตโนมัติในขณะที่ยังคงรักษาข้อดีของการจัดการสถานะแบบถาวร
ขั้นตอนที่ 1: สร้างฟังก์ชันอัปเดตข้อมูลบัญชี
async function updateAccountData() {
const account = state.account;
if (!account) {
return logout();
}
const data = await getAccount(account.user);
if (data.error) {
return logout();
}
updateState('account', data);
}
การทำความเข้าใจตรรกะของฟังก์ชันนี้:
- ตรวจสอบ ว่าผู้ใช้ล็อกอินอยู่หรือไม่ (state.account มีอยู่)
- เปลี่ยนเส้นทาง ไปยังหน้าล็อกเอาต์หากไม่มีเซสชันที่ถูกต้อง
- ดึง ข้อมูลบัญชีใหม่จากเซิร์ฟเวอร์โดยใช้ฟังก์ชัน
getAccount()ที่มีอยู่ - จัดการ ข้อผิดพลาดของเซิร์ฟเวอร์อย่างราบรื่นโดยการล็อกเอาต์เซสชันที่ไม่ถูกต้อง
- อัปเดต สถานะด้วยข้อมูลใหม่โดยใช้ระบบอัปเดตที่ควบคุม
- กระตุ้น การจัดการข้อมูลแบบถาวรใน localStorage โดยอัตโนมัติผ่านฟังก์ชัน
updateState()
ขั้นตอนที่ 2: สร้างฟังก์ชันรีเฟรชแดชบอร์ด
async function refresh() {
await updateAccountData();
updateDashboard();
}
สิ่งที่ฟังก์ชันรีเฟรชนี้ทำสำเร็จ:
- ประสานงาน กระบวนการรีเฟรชข้อมูลและการอัปเดต UI
- รอ ให้ข้อมูลใหม่โหลดก่อนอัปเดตการแสดงผล
- รับรอง ว่าแดชบอร์ดแสดงข้อมูลที่ทันสมัยที่สุด
- รักษา การแยกที่ชัดเจนระหว่างการจัดการข้อมูลและการอัปเดต UI
ขั้นตอนที่ 3: รวมเข้ากับระบบเส้นทาง
อัปเดตการกำหนดค่าเส้นทางของคุณเพื่อกระตุ้นการรีเฟรชโดยอัตโนมัติ:
const routes = {
'/login': { templateId: 'login' },
'/dashboard': { templateId: 'dashboard', init: refresh }
};
วิธีการทำงานของการรวมนี้:
- ดำเนินการ ฟังก์ชันรีเฟรชทุกครั้งที่โหลดเส้นทางแดชบอร์ด
- รับรอง ว่าข้อมูลใหม่จะแสดงเสมอเมื่อผู้ใช้ไปยังแดชบอร์ด
- รักษา โครงสร้างเส้นทางที่มีอยู่ในขณะที่เพิ่มความสดใหม่ของข้อมูล
- ให้ รูปแบบที่สอดคล้องกันสำหรับการเริ่มต้นเฉพาะเส้นทาง
การทดสอบระบบรีเฟรชข้อมูลของคุณ:
- ล็อกอินเข้าสู่แอปธนาคารของคุณ
- รันคำสั่ง curl จากก่อนหน้านี้เพื่อสร้างธุรกรรมใหม่
- รีเฟรชหน้าแดชบอร์ดหรือไปยังหน้าอื่นแล้วกลับมา
- ตรวจสอบว่าธุรกรรมใหม่ปรากฏทันที
🎉 สมดุลที่สมบูรณ์แบบ: แอปของคุณตอนนี้รวมประสบการณ์การใช้งานที่ราบรื่นของสถานะถาวรเข้ากับความถูกต้องของข้อมูลเซิร์ฟเวอร์ที่สดใหม่!
ความท้าทายของ GitHub Copilot Agent 🚀
ใช้โหมด Agent เพื่อทำความท้าทายต่อไปนี้:
คำอธิบาย: สร้างระบบการจัดการสถานะที่ครอบคลุมพร้อมฟังก์ชันย้อนกลับ/ทำซ้ำสำหรับแอปธนาคาร ความท้าทายนี้จะช่วยให้คุณฝึกฝนแนวคิดการจัดการสถานะขั้นสูง รวมถึงการติดตามประวัติสถานะ การอัปเดตแบบไม่เปลี่ยนแปลง และการซิงโครไนซ์กับส่วนติดต่อผู้ใช้
คำสั่ง: สร้างระบบการจัดการสถานะที่ปรับปรุงแล้วซึ่งรวมถึง: 1) อาร์เรย์ประวัติสถานะที่ติดตามสถานะก่อนหน้า, 2) ฟังก์ชันย้อนกลับและทำซ้ำที่สามารถย้อนกลับไปยังสถานะก่อนหน้า, 3) ปุ่ม UI สำหรับการย้อนกลับ/ทำซ้ำบนแดชบอร์ด, 4) ขีดจำกัดประวัติสูงสุด 10 สถานะเพื่อป้องกันปัญหาหน่วยความจำ, และ 5) การล้างประวัติอย่างเหมาะสมเมื่อผู้ใช้ออกจากระบบ รับรองว่าฟังก์ชันย้อนกลับ/ทำซ้ำทำงานร่วมกับการเปลี่ยนแปลงยอดคงเหลือบัญชีและยังคงอยู่หลังการรีเฟรชเบราว์เซอร์
เรียนรู้เพิ่มเติมเกี่ยวกับ โหมด Agent ที่นี่
🚀 ความท้าทาย: การปรับปรุงการจัดเก็บข้อมูล
การใช้งานของคุณตอนนี้จัดการเซสชันผู้ใช้ การรีเฟรชข้อมูล และการจัดการสถานะได้อย่างมีประสิทธิภาพ อย่างไรก็ตาม ลองพิจารณาว่าวิธีการปัจจุบันของเราสมดุลระหว่างประสิทธิภาพการจัดเก็บข้อมูลกับฟังก์ชันการทำงานได้ดีที่สุดหรือไม่
เหมือนกับนักหมากรุกที่แยกแยะระหว่างตัวหมากที่สำคัญและตัวหมากที่สามารถเสียได้ การจัดการสถานะที่มีประสิทธิภาพต้องระบุว่าข้อมูลใดที่ต้องจัดเก็บถาวรและข้อมูลใดที่ควรดึงจากเซิร์ฟเวอร์เสมอ
การวิเคราะห์การปรับปรุง:
ประเมินการใช้งาน localStorage ปัจจุบันของคุณและพิจารณาคำถามเชิงกลยุทธ์เหล่านี้:
- ข้อมูลขั้นต่ำที่จำเป็นในการรักษาการตรวจสอบสิทธิ์ของผู้ใช้คืออะไร?
- ข้อมูลใดที่เปลี่ยนแปลงบ่อยจนการแคชในเครื่องไม่มีประโยชน์?
- การปรับปรุงการจัดเก็บข้อมูลสามารถเพิ่มประสิทธิภาพได้โดยไม่ลดทอนประสบการณ์ผู้ใช้ได้อย่างไร?
กลยุทธ์การใช้งาน:
- ระบุ ข้อมูลสำคัญที่ต้องจัดเก็บถาวร (อาจเป็นเพียงข้อมูลการระบุตัวตนของผู้ใช้)
- ปรับเปลี่ยน การใช้งาน localStorage ของคุณเพื่อจัดเก็บเฉพาะข้อมูลเซสชันที่สำคัญ
- รับรอง ว่าข้อมูลใหม่จะถูกโหลดจากเซิร์ฟเวอร์เสมอเมื่อเยี่ยมชมแดชบอร์ด
- ทดสอบ ว่าวิธีการที่ปรับปรุงแล้วของคุณยังคงรักษาประสบการณ์ผู้ใช้เดิม
การพิจารณาขั้นสูง:
- เปรียบเทียบ ข้อดีข้อเสียระหว่างการจัดเก็บข้อมูลบัญชีทั้งหมดกับการจัดเก็บเฉพาะโทเค็นการตรวจสอบสิทธิ์
- บันทึก การตัดสินใจและเหตุผลของคุณสำหรับสมาชิกทีมในอนาคต
ความท้าทายนี้จะช่วยให้คุณคิดเหมือนนักพัฒนามืออาชีพที่พิจารณาทั้งประสบการณ์ผู้ใช้และประสิทธิภาพของแอปพลิเคชัน ใช้เวลาในการทดลองกับวิธีการต่าง ๆ!
แบบทดสอบหลังการบรรยาย
งานที่ได้รับมอบหมาย
นี่คือตัวอย่างผลลัพธ์หลังจากทำงานที่ได้รับมอบหมายเสร็จ:
ข้อจำกัดความรับผิดชอบ:
เอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI Co-op Translator แม้ว่าเราจะพยายามให้การแปลมีความถูกต้อง แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลสำคัญ ขอแนะนำให้ใช้บริการแปลภาษามืออาชีพ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความผิดที่เกิดจากการใช้การแปลนี้

