𝗕𝗲𝘄𝗮𝗿𝗲 𝗼𝗳 𝗹𝗼𝗱𝗮𝘀𝗵.𝗺𝗲𝗺𝗼𝗶𝘇𝗲
lodash.memoize ดูเหมือนจะเป็นการเพิ่มประสิทธิภาพที่ได้มาฟรีๆ เพียงแค่คุณนำฟังก์ชันมาครอบไว้ คุณก็จะได้ cache มาใช้งาน
แต่พฤติกรรมเริ่มต้นของมันมีกับดักซ่อนอยู่ เพราะมันจะสร้าง cache key จากอาร์กิวเมนต์แรกเพียงอย่างเดียว และจะละเลยอาร์กิวเมนต์อื่นๆ ทั้งหมด
หากคุณใช้อาร์กิวเมนต์เพียงตัวเดียว คุณจะปลอดภัย แต่ถ้าคุณใช้ตั้งแต่สองตัวขึ้นไป คุณกำลังสร้างบั๊ก
ดูตัวอย่างนี้:
const add = memoize((a, b) => a + b);
add(1, 2); // คืนค่า 3 โดยเก็บผลลัพธ์ไว้ใน cache ภายใต้ key 1
add(1, 9); // คืนค่า 3 ซึ่งผิด เพราะจริงๆ ควรจะเป็น 10
Lodash เห็นเลข 1 อีกครั้ง มันจึงพบเลข 1 ใน cache และคืนค่าผลลัพธ์เดิมออกมา โดยที่มันไม่ได้สนใจเลข 9 เลย
การจัดรูปแบบสกุลเงินเป็นกับดักที่พบได้บ่อย
const formatPrice = memoize((amount, currency) =>
new Intl.NumberFormat('en', { style: 'currency', currency }).format(amount)
);
formatPrice(100, 'USD'); // คืนค่า "$100.00" โดยมี key คือ 100
formatPrice(100, 'EUR'); // คืนค่า "$100.00" ซึ่งผิด
การเรียกใช้งานครั้งที่สองจะละเลย 'EUR' เพราะมันเห็น 100 ใน cache จึงคืนค่าเป็นดอลลาร์แทนที่จะเป็นยูโร โดยที่ไม่มีข้อผิดพลาด (error) หรือคำเตือน (warning) ใดๆ ปรากฏขึ้นเลย คุณแค่แสดงจำนวนเงินที่ผิดให้กับผู้ใช้งานของคุณ
คุณต้องระบุอาร์กิวเมนต์ที่สองเพื่อกำหนด cache key และ key นี้จะต้องครอบคลุมทุกอินพุตที่ส่งเข้ามา
const formatPrice = memoize(
(amount, currency) =>
new Intl.NumberFormat('en', { style: 'currency', currency }).format(amount),
(amount, currency) => \${amount}|${currency}` );`
formatPrice(100, 'USD'); // "$100.00"
formatPrice(100, 'EUR'); // "€100.00"
Key จะต้องครอบคลุมทุกสิ่งที่ส่งผลต่อการเปลี่ยนแปลงของผลลัพธ์
ข้อคิดทิ้งท้าย: การทำ memoization เพิ่มความเสี่ยง ควรใช้เฉพาะเมื่อฟังก์ชันนั้นมีการประมวลผลที่หนัก (expensive) และต้องทำงานบ่อยครั้งด้วยอินพุตเดิมๆ เท่านั้น สำหรับฟังก์ชันทั่วไปที่ทำงานไม่ซับซ้อน ให้เรียกใช้งานตามปกติเถอะ เพราะความเสี่ยงที่จะเกิดบั๊กมักจะสูงกว่าความเร็วที่คุณจะได้รับ
สรุปประเด็นสำคัญ:
- Key เริ่มต้นจะใช้อาร์กิวเมนต์แรกเพียงตัวเดียว
- ใช้ resolver เพื่อรวมอาร์กิวเมนต์ทั้งหมดไว้ใน key
- Key ที่ดีควรสะท้อนถึงทุกสิ่งที่ทำให้ผลลัพธ์เปลี่ยนแปลง
- อย่าใช้ memoize กับฟังก์ชันที่ทำงานได้รวดเร็วอยู่แล้ว (cheap functions)
Source: https://dev.to/figsify/beware-of-lodashmemoize-it-only-remembers-the-first-argument-4cjl