Uważaj na lodash.memoize
Lodash memoize wydaje się darmowym zyskiem na wydajności. Owijasz funkcję i otrzymujesz pamięć podręczną (cache).
Ale domyślne zachowanie kryje pułapkę. Klucz cache'u jest budowany wyłącznie na podstawie pierwszego argumentu. Wszystkie pozostałe argumenty są ignorowane.
Jeśli używasz jednego argumentu, jesteś bezpieczny. Jeśli używasz dwóch lub więcej, tworzysz błędy.
Spójrz na ten przykład:
const add = memoize((a, b) => a + b);
add(1, 2); // Zwraca 3. Wynik jest zapisywany w cache pod kluczem 1.
add(1, 9); // Zwraca 3. To błąd. Powinno być 10.
Lodash ponownie widzi 1. Znajduje 1 w cache. Zwraca stary wynik. Nigdy nie bierze pod uwagę cyfry 9.
Formatowanie walut to częsta pułapka.
const formatPrice = memoize((amount, currency) =>
new Intl.NumberFormat('en', { style: 'currency', currency }).format(amount)
);
formatPrice(100, 'USD'); // Zwraca "$100.00". Kluczem jest 100.
formatPrice(100, 'EUR'); // Zwraca "$100.00". To błąd.
Drugie wywołanie ignoruje 'EUR'. Widzi 100 w cache i zwraca dolary zamiast euro. Nie pojawia się żaden błąd. Nie ma żadnego ostrzeżenia. Po prostu wyświetlasz użytkownikom błędną kwotę.
Musisz podać drugi argument, aby zdefiniować klucz cache'u. Klucz ten musi obejmować każdy argument wejściowy.
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"
Klucz musi uwzględniać wszystko, co wpływa na wynik.
Na koniec: memoizacja niesie ze sobą ryzyko. Używaj jej tylko wtedy, gdy funkcja jest kosztowna obliczeniowo i jest często wywoływana z tymi samymi argumentami. W przypadku prostych funkcji po prostu je wywołuj. Ryzyko wystąpienia błędu jest często większe niż zysk na prędkości.
Kluczowe wnioski:
- Domyślne klucze używają tylko pierwszego argumentu.
- Użyj funkcji resolvera, aby uwzględnić wszystkie argumenty w kluczu.
- Dobry klucz odzwierciedla wszystko, co zmienia wynik.
- Nie używaj memoize dla funkcji o niskim koszcie obliczeniowym.
Source: https://dev.to/figsify/beware-of-lodashmemoize-it-only-remembers-the-first-argument-4cjl