JavaScript's WeakRef ಮತ್ತು FinalizationRegistry ಬಳಸಿ ಮೆಮೊರಿ-ದಕ್ಷ ಅಬ್ಸರ್ವರ್ ಪ್ಯಾಟರ್ನ್ ರಚಿಸುವ ಕುರಿತು ಆಳವಾದ ವಿಶ್ಲೇಷಣೆ. ದೊಡ್ಡ ಪ್ರಮಾಣದ ಅಪ್ಲಿಕೇಶನ್ಗಳಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆಗಳನ್ನು ತಡೆಯಲು ಕಲಿಯಿರಿ.
ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ವೀಕ್ರೆಫ್ ಅಬ್ಸರ್ವರ್ ಪ್ಯಾಟರ್ನ್: ಮೆಮೊರಿ-ಅವೇರ್ ಈವೆಂಟ್ ಸಿಸ್ಟಮ್ಗಳನ್ನು ನಿರ್ಮಿಸುವುದು
ಆಧುನಿಕ ವೆಬ್ ಅಭಿವೃದ್ಧಿಯ ಜಗತ್ತಿನಲ್ಲಿ, ಡೈನಾಮಿಕ್ ಮತ್ತು ಪ್ರತಿಕ್ರಿಯಾತ್ಮಕ ಬಳಕೆದಾರ ಅನುಭವಗಳನ್ನು ರಚಿಸಲು ಸಿಂಗಲ್ ಪೇಜ್ ಅಪ್ಲಿಕೇಶನ್ಗಳು (SPAs) ಮಾನದಂಡವಾಗಿ ಮಾರ್ಪಟ್ಟಿವೆ. ಈ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಸಾಮಾನ್ಯವಾಗಿ ದೀರ್ಘಕಾಲದವರೆಗೆ ಚಾಲನೆಯಲ್ಲಿರುತ್ತವೆ, ಸಂಕೀರ್ಣ ಸ್ಥಿತಿಯನ್ನು ನಿರ್ವಹಿಸುತ್ತವೆ ಮತ್ತು ಅಸಂಖ್ಯಾತ ಬಳಕೆದಾರ ಸಂವಹನಗಳನ್ನು ನಿರ್ವಹಿಸುತ್ತವೆ. ಆದಾಗ್ಯೂ, ಈ ದೀರ್ಘಾಯುಷ್ಯವು ಗುಪ್ತ ವೆಚ್ಚದೊಂದಿಗೆ ಬರುತ್ತದೆ: ಮೆಮೊರಿ ಸೋರಿಕೆಗಳ ಹೆಚ್ಚಿದ ಅಪಾಯ. ಮೆಮೊರಿ ಸೋರಿಕೆ, ಅಪ್ಲಿಕೇಶನ್ ಇನ್ನು ಮುಂದೆ ಅಗತ್ಯವಿಲ್ಲದ ಮೆಮೊರಿಯನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳುವಲ್ಲಿ, ಕಾಲಾನಂತರದಲ್ಲಿ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ, ಇದು ನಿಧಾನಗತಿ, ಬ್ರೌಸರ್ ಕ್ರ್ಯಾಶ್ಗಳು ಮತ್ತು ಕಳಪೆ ಬಳಕೆದಾರ ಅನುಭವಕ್ಕೆ ಕಾರಣವಾಗುತ್ತದೆ. ಈ ಸೋರಿಕೆಗಳ ಸಾಮಾನ್ಯ ಮೂಲಗಳಲ್ಲಿ ಒಂದು ಮೂಲಭೂತ ವಿನ್ಯಾಸ ಮಾದರಿಯಲ್ಲಿ ಅಡಗಿದೆ: ಅಬ್ಸರ್ವರ್ ಪ್ಯಾಟರ್ನ್.
ಅಬ್ಸರ್ವರ್ ಪ್ಯಾಟರ್ನ್ ಈವೆಂಟ್-ಡ್ರೈವನ್ ಆರ್ಕಿಟೆಕ್ಚರ್ನ ಮೂಲಾಧಾರವಾಗಿದೆ, ಇದು ಆಬ್ಜೆಕ್ಟ್ಗಳಿಗೆ (ಅಬ್ಸರ್ವರ್ಗಳು) ಕೇಂದ್ರ ಆಬ್ಜೆಕ್ಟ್ನಿಂದ (ಸಬ್ಜೆಕ್ಟ್) ಅಪ್ಡೇಟ್ಗಳನ್ನು ಚಂದಾದಾರರಾಗಲು ಮತ್ತು ಸ್ವೀಕರಿಸಲು ಅನುವು ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದು ಸೊಗಸಾದ, ಸರಳ ಮತ್ತು ನಂಬಲಾಗದಷ್ಟು ಉಪಯುಕ್ತವಾಗಿದೆ. ಆದರೆ ಇದರ ಕ್ಲಾಸಿಕ್ ಅನುಷ್ಠಾನವು ಒಂದು ನಿರ್ಣಾಯಕ ದೋಷವನ್ನು ಹೊಂದಿದೆ: ಸಬ್ಜೆಕ್ಟ್ ತನ್ನ ಅಬ್ಸರ್ವರ್ಗಳಿಗೆ ಬಲವಾದ ಉಲ್ಲೇಖಗಳನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ. ಅಪ್ಲಿಕೇಶನ್ನ ಉಳಿದ ಭಾಗಕ್ಕೆ ಅಬ್ಸರ್ವರ್ ಇನ್ನು ಮುಂದೆ ಅಗತ್ಯವಿಲ್ಲದಿದ್ದರೆ, ಆದರೆ ಡೆವಲಪರ್ ಅದನ್ನು ಸಬ್ಜೆಕ್ಟ್ನಿಂದ ಸ್ಪಷ್ಟವಾಗಿ ಅನ್ಸಬ್ಸ್ಕ್ರೈಬ್ ಮಾಡಲು ಮರೆತರೆ, ಅದನ್ನು ಎಂದಿಗೂ ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹಿಸಲಾಗುವುದಿಲ್ಲ. ಅದು ಮೆಮೊರಿಯಲ್ಲಿ ಸಿಕ್ಕಿಹಾಕಿಕೊಂಡಿರುತ್ತದೆ, ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ನ ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಕಾಡುವ ಒಂದು ಪ್ರೇತದಂತೆ.
ಇಲ್ಲಿ ಆಧುನಿಕ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್, ಅದರ ECMAScript 2021 (ES12) ವೈಶಿಷ್ಟ್ಯಗಳೊಂದಿಗೆ, ಶಕ್ತಿಶಾಲಿ ಪರಿಹಾರವನ್ನು ಒದಗಿಸುತ್ತದೆ. WeakRef ಮತ್ತು FinalizationRegistry ಅನ್ನು ಬಳಸಿಕೊಳ್ಳುವ ಮೂಲಕ, ನಾವು ಮೆಮೊರಿ-ಅವೇರ್ ಅಬ್ಸರ್ವರ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನಿರ್ಮಿಸಬಹುದು, ಅದು ತನ್ನಷ್ಟಕ್ಕೆ ತಾನೇ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸ್ವಚ್ಛಗೊಳಿಸುತ್ತದೆ, ಈ ಸಾಮಾನ್ಯ ಸೋರಿಕೆಗಳನ್ನು ತಡೆಯುತ್ತದೆ. ಈ ಲೇಖನವು ಈ ಸುಧಾರಿತ ತಂತ್ರದ ಆಳವಾದ ವಿಶ್ಲೇಷಣೆಯಾಗಿದೆ. ನಾವು ಸಮಸ್ಯೆಯನ್ನು ಅನ್ವೇಷಿಸುತ್ತೇವೆ, ಪರಿಕರಗಳನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುತ್ತೇವೆ, ಮೊದಲಿನಿಂದಲೂ ದೃಢವಾದ ಅನುಷ್ಠಾನವನ್ನು ನಿರ್ಮಿಸುತ್ತೇವೆ ಮತ್ತು ನಿಮ್ಮ ಜಾಗತಿಕ ಅಪ್ಲಿಕೇಶನ್ಗಳಲ್ಲಿ ಈ ಶಕ್ತಿಶಾಲಿ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ಯಾವಾಗ ಮತ್ತು ಎಲ್ಲಿ ಅನ್ವಯಿಸಬೇಕು ಎಂಬುದನ್ನು ಚರ್ಚಿಸುತ್ತೇವೆ.
ಪ್ರಮುಖ ಸಮಸ್ಯೆಯನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು: ಕ್ಲಾಸಿಕ್ ಅಬ್ಸರ್ವರ್ ಪ್ಯಾಟರ್ನ್ ಮತ್ತು ಅದರ ಮೆಮೊರಿ ಹೆಜ್ಜೆಗುರುತು
ನಾವು ಪರಿಹಾರವನ್ನು ಪ್ರಶಂಸಿಸುವ ಮೊದಲು, ನಾವು ಸಮಸ್ಯೆಯನ್ನು ಸಂಪೂರ್ಣವಾಗಿ ಗ್ರಹಿಸಬೇಕು. ಅಬ್ಸರ್ವರ್ ಪ್ಯಾಟರ್ನ್, ಪಬ್ಲಿಷರ್-ಸಬ್ಸ್ಕ್ರೈಬರ್ ಪ್ಯಾಟರ್ನ್ ಎಂದೂ ಕರೆಯಲ್ಪಡುತ್ತದೆ, ಇದು ಘಟಕಗಳನ್ನು ಡಿಕಪಲ್ ಮಾಡಲು ವಿನ್ಯಾಸಗೊಳಿಸಲಾಗಿದೆ. ಒಂದು Subject (ಅಥವಾ Publisher) ತನ್ನ ಅವಲಂಬಿತರ ಪಟ್ಟಿಯನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ, ಇದನ್ನು Observers (ಅಥವಾ Subscribers) ಎಂದು ಕರೆಯಲಾಗುತ್ತದೆ. Subject ನ ಸ್ಥಿತಿ ಬದಲಾದಾಗ, ಅದು ತನ್ನ ಎಲ್ಲ Observers ಗಳಿಗೆ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತಿಳಿಸುತ್ತದೆ, ಸಾಮಾನ್ಯವಾಗಿ update() ನಂತಹ ನಿರ್ದಿಷ್ಟ ವಿಧಾನವನ್ನು ಅವುಗಳ ಮೇಲೆ ಕರೆ ಮಾಡುವ ಮೂಲಕ.
ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ನಲ್ಲಿ ಸರಳ, ಕ್ಲಾಸಿಕ್ ಅನುಷ್ಠಾನವನ್ನು ನೋಡೋಣ.
ಒಂದು ಸರಳ ಸಬ್ಜೆಕ್ಟ್ ಅನುಷ್ಠಾನ
ಇಲ್ಲಿ ಒಂದು ಮೂಲ ಸಬ್ಜೆಕ್ಟ್ ವರ್ಗವಿದೆ. ಇದು ಚಂದಾದಾರರಾಗಲು, ಚಂದಾದಾರಿಕೆಯನ್ನು ರದ್ದುಗೊಳಿಸಲು ಮತ್ತು ಅಬ್ಸರ್ವರ್ಗಳಿಗೆ ತಿಳಿಸಲು ವಿಧಾನಗಳನ್ನು ಹೊಂದಿದೆ.
class ClassicSubject {
constructor() {
this.observers = [];
}
subscribe(observer) {
this.observers.push(observer);
console.log(`${observer.name} has subscribed.`);
}
unsubscribe(observer) {
this.observers = this.observers.filter(obs => obs !== observer);
console.log(`${observer.name} has unsubscribed.`);
}
notify(data) {
console.log('Notifying observers...');
this.observers.forEach(observer => observer.update(data));
}
}
ಮತ್ತು ಇಲ್ಲಿ ಸಬ್ಜೆಕ್ಟ್ಗೆ ಚಂದಾದಾರರಾಗಬಹುದಾದ ಸರಳ ಅಬ್ಸರ್ವರ್ ವರ್ಗವಿದೆ.
class Observer {
constructor(name) {
this.name = name;
}
update(data) {
console.log(`${this.name} received data: ${data}`);
}
}
ಗುಪ್ತ ಅಪಾಯ: ಉಳಿದಿರುವ ಉಲ್ಲೇಖಗಳು
ನಮ್ಮ ಅಬ್ಸರ್ವರ್ಗಳ ಜೀವಿತಾವಧಿಯನ್ನು ನಾವು ಶ್ರದ್ಧೆಯಿಂದ ನಿರ್ವಹಿಸುವವರೆಗೆ ಈ ಅನುಷ್ಠಾನವು ಸಂಪೂರ್ಣವಾಗಿ ಉತ್ತಮವಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ. ನಾವು ನಿರ್ವಹಿಸದಿದ್ದಾಗ ಸಮಸ್ಯೆ ಉಂಟಾಗುತ್ತದೆ. ದೊಡ್ಡ ಅಪ್ಲಿಕೇಶನ್ನಲ್ಲಿ ಸಾಮಾನ್ಯ ಸನ್ನಿವೇಶವನ್ನು ಪರಿಗಣಿಸಿ: ದೀರ್ಘಕಾಲಿಕ ಜಾಗತಿಕ ಡೇಟಾ ಸ್ಟೋರ್ (ಸಬ್ಜೆಕ್ಟ್) ಮತ್ತು ಆ ಡೇಟಾದ ಕೆಲವು ಭಾಗವನ್ನು ಪ್ರದರ್ಶಿಸುವ ತಾತ್ಕಾಲಿಕ UI ಕಾಂಪೊನೆಂಟ್ (ಅಬ್ಸರ್ವರ್).
ಈ ಸನ್ನಿವೇಶವನ್ನು ಅನುಕರಿಸೋಣ:
const dataStore = new ClassicSubject();
function manageUIComponent() {
let chartComponent = new Observer('ChartComponent');
dataStore.subscribe(chartComponent);
// The component does its job...
// Now, the user navigates away, and the component is no longer needed.
// A developer might forget to add the cleanup code:
// dataStore.unsubscribe(chartComponent);
chartComponent = null; // We release our reference to the component.
}
manageUIComponent();
// Later in the application lifecycle...
dataStore.notify('New data available!');
`manageUIComponent` ಕಾರ್ಯದಲ್ಲಿ, ನಾವು `chartComponent` ಅನ್ನು ರಚಿಸುತ್ತೇವೆ ಮತ್ತು ಅದನ್ನು ನಮ್ಮ `dataStore` ಗೆ ಚಂದಾದಾರರಾಗುತ್ತೇವೆ. ನಂತರ, ನಾವು `chartComponent` ಅನ್ನು `null` ಗೆ ಹೊಂದಿಸುತ್ತೇವೆ, ನಾವು ಅದರೊಂದಿಗೆ ಕೆಲಸ ಮುಗಿಸಿದ್ದೇವೆ ಎಂದು ಸೂಚಿಸುತ್ತದೆ. ಈ ಆಬ್ಜೆಕ್ಟ್ಗೆ ಇನ್ನು ಮುಂದೆ ಯಾವುದೇ ಉಲ್ಲೇಖಗಳಿಲ್ಲ ಎಂದು ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಗಾರ್ಬೇಜ್ ಕಲೆಕ್ಟರ್ (GC) ಗುರುತಿಸಿ ಅದರ ಮೆಮೊರಿಯನ್ನು ಮರಳಿ ಪಡೆಯುತ್ತದೆ ಎಂದು ನಾವು ನಿರೀಕ್ಷಿಸುತ್ತೇವೆ.
ಆದರೆ ಇನ್ನೊಂದು ಉಲ್ಲೇಖವಿದೆ! `dataStore.observers` ಅರೇ ಇನ್ನೂ `chartComponent` ಆಬ್ಜೆಕ್ಟ್ಗೆ ನೇರ, ಬಲವಾದ ಉಲ್ಲೇಖವನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಂಡಿದೆ. ಈ ಒಂದೇ ಒಂದು ಉಳಿದಿರುವ ಉಲ್ಲೇಖದಿಂದಾಗಿ, ಗಾರ್ಬೇಜ್ ಕಲೆಕ್ಟರ್ ಮೆಮೊರಿಯನ್ನು ಮರಳಿ ಪಡೆಯಲು ಸಾಧ್ಯವಿಲ್ಲ. `chartComponent` ಆಬ್ಜೆಕ್ಟ್ ಮತ್ತು ಅದು ಹಿಡಿದಿಟ್ಟುಕೊಂಡಿರುವ ಯಾವುದೇ ಸಂಪನ್ಮೂಲಗಳು `dataStore` ನ ಸಂಪೂರ್ಣ ಜೀವಿತಾವಧಿಯಲ್ಲಿ ಮೆಮೊರಿಯಲ್ಲಿ ಉಳಿಯುತ್ತವೆ. ಇದು ಪದೇ ಪದೇ ಸಂಭವಿಸಿದರೆ - ಉದಾಹರಣೆಗೆ, ಬಳಕೆದಾರರು ಪ್ರತಿ ಬಾರಿ ಮಾಡಲ್ ವಿಂಡೋವನ್ನು ತೆರೆದು ಮುಚ್ಚಿದಾಗ - ಅಪ್ಲಿಕೇಶನ್ನ ಮೆಮೊರಿ ಬಳಕೆ ಅನಿರ್ದಿಷ್ಟವಾಗಿ ಬೆಳೆಯುತ್ತದೆ. ಇದು ಕ್ಲಾಸಿಕ್ ಮೆಮೊರಿ ಸೋರಿಕೆ.
ಒಂದು ಹೊಸ ಭರವಸೆ: WeakRef ಮತ್ತು FinalizationRegistry ಪರಿಚಯ
ECMAScript 2021 ಈ ರೀತಿಯ ಮೆಮೊರಿ ನಿರ್ವಹಣೆಯ ಸವಾಲುಗಳನ್ನು ನಿರ್ವಹಿಸಲು ನಿರ್ದಿಷ್ಟವಾಗಿ ವಿನ್ಯಾಸಗೊಳಿಸಲಾದ ಎರಡು ಹೊಸ ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಪರಿಚಯಿಸಿತು: `WeakRef` ಮತ್ತು `FinalizationRegistry`. ಅವು ಸುಧಾರಿತ ಸಾಧನಗಳಾಗಿವೆ ಮತ್ತು ಎಚ್ಚರಿಕೆಯಿಂದ ಬಳಸಬೇಕು, ಆದರೆ ನಮ್ಮ ಅಬ್ಸರ್ವರ್ ಪ್ಯಾಟರ್ನ್ ಸಮಸ್ಯೆಗೆ, ಅವು ಪರಿಪೂರ್ಣ ಪರಿಹಾರಗಳಾಗಿವೆ.
WeakRef ಎಂದರೇನು?
ಒಂದು `WeakRef` ಆಬ್ಜೆಕ್ಟ್ ತನ್ನ ಟಾರ್ಗೆಟ್ ಎಂದು ಕರೆಯಲ್ಪಡುವ ಮತ್ತೊಂದು ಆಬ್ಜೆಕ್ಟ್ಗೆ দুর্বল ಉಲ್ಲೇಖವನ್ನು (weak reference) ಹೊಂದಿರುತ್ತದೆ. ದುರ್ಬಲ ಉಲ್ಲೇಖ ಮತ್ತು ಸಾಮಾನ್ಯ (ಬಲವಾದ) ಉಲ್ಲೇಖದ ನಡುವಿನ ಪ್ರಮುಖ ವ್ಯತ್ಯಾಸವೆಂದರೆ: ದುರ್ಬಲ ಉಲ್ಲೇಖವು ಅದರ ಟಾರ್ಗೆಟ್ ಆಬ್ಜೆಕ್ಟ್ ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹವಾಗುವುದನ್ನು ತಡೆಯುವುದಿಲ್ಲ.
ಒಂದು ಆಬ್ಜೆಕ್ಟ್ಗೆ ಇರುವ ಏಕೈಕ ಉಲ್ಲೇಖಗಳು ದುರ್ಬಲ ಉಲ್ಲೇಖಗಳಾಗಿದ್ದರೆ, ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಎಂಜಿನ್ ಆ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ನಾಶಪಡಿಸಲು ಮತ್ತು ಅದರ ಮೆಮೊರಿಯನ್ನು ಮರಳಿ ಪಡೆಯಲು ಮುಕ್ತವಾಗಿದೆ. ಇದು ನಮ್ಮ ಅಬ್ಸರ್ವರ್ ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು ನಮಗೆ ಬೇಕಾಗಿರುವುದು.
`WeakRef` ಅನ್ನು ಬಳಸಲು, ನೀವು ಅದರ ಒಂದು ನಿದರ್ಶನವನ್ನು ರಚಿಸಿ, ಟಾರ್ಗೆಟ್ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಕನ್ಸ್ಟ್ರಕ್ಟರ್ಗೆ ರವಾನಿಸುತ್ತೀರಿ. ನಂತರ ಟಾರ್ಗೆಟ್ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು, ನೀವು `deref()` ವಿಧಾನವನ್ನು ಬಳಸುತ್ತೀರಿ.
let targetObject = { id: 42 };
const weakRefToObject = new WeakRef(targetObject);
// ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು:
const retrievedObject = weakRefToObject.deref();
if (retrievedObject) {
console.log(`Object is still alive: ${retrievedObject.id}`); // ಔಟ್ಪುಟ್: ಆಬ್ಜೆಕ್ಟ್ ಇನ್ನೂ ಜೀವಂತವಾಗಿದೆ: 42
} else {
console.log('Object has been garbage collected.');
}
`deref()` `undefined` ಅನ್ನು ಹಿಂತಿರುಗಿಸಬಹುದು ಎಂಬುದು ನಿರ್ಣಾಯಕ ಭಾಗ. `targetObject` ಗೆ ಯಾವುದೇ ಬಲವಾದ ಉಲ್ಲೇಖಗಳು ಅಸ್ತಿತ್ವದಲ್ಲಿಲ್ಲದ ಕಾರಣ ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹಿಸಲ್ಪಟ್ಟಿದ್ದರೆ ಇದು ಸಂಭವಿಸುತ್ತದೆ. ಈ ನಡವಳಿಕೆಯು ನಮ್ಮ ಮೆಮೊರಿ-ಅವೇರ್ ಅಬ್ಸರ್ವರ್ ಪ್ಯಾಟರ್ನ್ನ ಅಡಿಪಾಯವಾಗಿದೆ.
FinalizationRegistry ಎಂದರೇನು?
`WeakRef` ಒಂದು ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಸಂಗ್ರಹಿಸಲು ಅನುಮತಿಸಿದರೂ, ಅದನ್ನು ಯಾವಾಗ ಸಂಗ್ರಹಿಸಲಾಗಿದೆ ಎಂದು ತಿಳಿಯಲು ಇದು ನಮಗೆ ಸ್ಪಷ್ಟ ಮಾರ್ಗವನ್ನು ನೀಡುವುದಿಲ್ಲ. ನಾವು ನಿಯತಕಾಲಿಕವಾಗಿ `deref()` ಅನ್ನು ಪರಿಶೀಲಿಸಬಹುದು ಮತ್ತು ನಮ್ಮ ಅಬ್ಸರ್ವರ್ ಪಟ್ಟಿಯಿಂದ `undefined` ಫಲಿತಾಂಶಗಳನ್ನು ತೆಗೆದುಹಾಕಬಹುದು, ಆದರೆ ಅದು ಅಸಮರ್ಥವಾಗಿದೆ. ಇಲ್ಲಿ `FinalizationRegistry` ಬರುತ್ತದೆ.
ನೋಂದಾಯಿತ ಆಬ್ಜೆಕ್ಟ್ ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹಿಸಲ್ಪಟ್ಟ ನಂತರ ಕಾರ್ಯಗತಗೊಳಿಸಲಾಗುವ ಕಾಲ್ಬ್ಯಾಕ್ ಕಾರ್ಯವನ್ನು ನೋಂದಾಯಿಸಲು `FinalizationRegistry` ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಇದು ಮರಣೋತ್ತರ ಸ್ವಚ್ಛಗೊಳಿಸುವ ಒಂದು ಕಾರ್ಯವಿಧಾನವಾಗಿದೆ.
ಇದು ಹೇಗೆ ಕೆಲಸ ಮಾಡುತ್ತದೆ ಎಂಬುದು ಇಲ್ಲಿದೆ:
- ನೀವು ಕ್ಲೀನಪ್ ಕಾಲ್ಬ್ಯಾಕ್ನೊಂದಿಗೆ ರಿಜಿಸ್ಟ್ರಿಯನ್ನು ರಚಿಸುತ್ತೀರಿ.
- ನೀವು ರಿಜಿಸ್ಟ್ರಿಯೊಂದಿಗೆ ಒಂದು ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು `register()` ಮಾಡುತ್ತೀರಿ. ನೀವು `heldValue` ಅನ್ನು ಸಹ ಒದಗಿಸಬಹುದು, ಇದು ಆಬ್ಜೆಕ್ಟ್ ಸಂಗ್ರಹಿಸಿದಾಗ ನಿಮ್ಮ ಕಾಲ್ಬ್ಯಾಕ್ಗೆ ರವಾನೆಯಾಗುವ ಡೇಟಾ ಭಾಗವಾಗಿದೆ. ಈ `heldValue` ಆಬ್ಜೆಕ್ಟ್ಗೆ ನೇರ ಉಲ್ಲೇಖವಾಗಿರಬಾರದು, ಏಕೆಂದರೆ ಅದು ಉದ್ದೇಶವನ್ನು ವಿಫಲಗೊಳಿಸುತ್ತದೆ!
// 1. ಕ್ಲೀನಪ್ ಕಾಲ್ಬ್ಯಾಕ್ನೊಂದಿಗೆ ರಿಜಿಸ್ಟ್ರಿಯನ್ನು ರಚಿಸಿ
const registry = new FinalizationRegistry(heldValue => {
console.log(`An object has been garbage collected. Cleanup token: ${heldValue}`);
});
(function() {
let objectToTrack = { name: 'Temporary Data' };
let cleanupToken = 'temp-data-123';
// 2. ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ನೋಂದಾಯಿಸಿ ಮತ್ತು ಸ್ವಚ್ಛಗೊಳಿಸುವ ಟೋಕನ್ ಒದಗಿಸಿ
registry.register(objectToTrack, cleanupToken);
// objectToTrack ಇಲ್ಲಿ ವ್ಯಾಪ್ತಿಯಿಂದ ಹೊರಗೆ ಹೋಗುತ್ತದೆ
})();
// ಭವಿಷ್ಯದಲ್ಲಿ ಕೆಲವು ಹಂತದಲ್ಲಿ, GC ಚಾಲನೆಯಾದ ನಂತರ, ಕನ್ಸೋಲ್ನಲ್ಲಿ ಲಾಗ್ ಆಗುತ್ತದೆ:
// "ಒಂದು ಆಬ್ಜೆಕ್ಟ್ ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹವಾಗಿದೆ. ಕ್ಲೀನಪ್ ಟೋಕನ್: temp-data-123"
ಪ್ರಮುಖ ಎಚ್ಚರಿಕೆಗಳು ಮತ್ತು ಉತ್ತಮ ಅಭ್ಯಾಸಗಳು
ನಾವು ಅನುಷ್ಠಾನಕ್ಕೆ ಧುಮುಕುವ ಮೊದಲು, ಈ ಪರಿಕರಗಳ ಸ್ವರೂಪವನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದು ನಿರ್ಣಾಯಕ. ಗಾರ್ಬೇಜ್ ಕಲೆಕ್ಟರ್ನ ನಡವಳಿಕೆಯು ಅನುಷ್ಠಾನ-ಅವಲಂಬಿತವಾಗಿದೆ ಮತ್ತು ಅನಿಶ್ಚಿತವಾಗಿರುತ್ತದೆ. ಇದರರ್ಥ:
- ಒಂದು ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಯಾವಾಗ ಸಂಗ್ರಹಿಸಲಾಗುತ್ತದೆ ಎಂಬುದನ್ನು ನೀವು ಊಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅದು ತಲುಪಲಾಗದ ನಂತರ ಸೆಕೆಂಡುಗಳು, ನಿಮಿಷಗಳು ಅಥವಾ ಅದಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಮಯದ ನಂತರ ಆಗಿರಬಹುದು.
- ಸಕಾಲಿಕ ಅಥವಾ ಊಹಿಸಬಹುದಾದ ರೀತಿಯಲ್ಲಿ ರನ್ ಆಗಲು ನೀವು `FinalizationRegistry` ಕಾಲ್ಬ್ಯಾಕ್ಗಳನ್ನು ಅವಲಂಬಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಅವು ಸ್ವಚ್ಛಗೊಳಿಸುವಿಕೆಗಾಗಿ, ನಿರ್ಣಾಯಕ ಅಪ್ಲಿಕೇಶನ್ ತರ್ಕಕ್ಕಾಗಿ ಅಲ್ಲ.
- `WeakRef` ಮತ್ತು `FinalizationRegistry` ನ ಅತಿಯಾದ ಬಳಕೆಯು ಕೋಡ್ ಅನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಕಷ್ಟಕರವಾಗಿಸಬಹುದು. ಆಬ್ಜೆಕ್ಟ್ ಜೀವಿತಾವಧಿಗಳು ಸ್ಪಷ್ಟ ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದಾದರೆ ಯಾವಾಗಲೂ ಸರಳ ಪರಿಹಾರಗಳನ್ನು (ಸ್ಪಷ್ಟ `unsubscribe` ಕರೆಗಳಂತಹ) ಆದ್ಯತೆ ನೀಡಿ.
ಈ ವೈಶಿಷ್ಟ್ಯಗಳು ಒಂದು ಆಬ್ಜೆಕ್ಟ್ನ (ಅಬ್ಸರ್ವರ್) ಜೀವಿತಾವಧಿಯು ಇನ್ನೊಂದು ಆಬ್ಜೆಕ್ಟ್ನಿಂದ (ಸಬ್ಜೆಕ್ಟ್) ನಿಜವಾಗಿಯೂ ಸ್ವತಂತ್ರವಾಗಿರುವ ಮತ್ತು ತಿಳಿದಿಲ್ಲದ ಸಂದರ್ಭಗಳಿಗೆ ಉತ್ತಮವಾಗಿ ಸೂಕ್ತವಾಗಿವೆ.
`WeakRefObserver` ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನಿರ್ಮಿಸುವುದು: ಹಂತ-ಹಂತದ ಅನುಷ್ಠಾನ
ಈಗ, ಮೆಮೊರಿ-ಸುರಕ್ಷಿತ `WeakRefSubject` ವರ್ಗವನ್ನು ನಿರ್ಮಿಸಲು `WeakRef` ಮತ್ತು `FinalizationRegistry` ಅನ್ನು ಸಂಯೋಜಿಸೋಣ.
ಹಂತ 1: `WeakRefSubject` ವರ್ಗ ರಚನೆ
ನಮ್ಮ ಹೊಸ ವರ್ಗವು ನೇರ ಉಲ್ಲೇಖಗಳ ಬದಲಿಗೆ ಅಬ್ಸರ್ವರ್ಗಳಿಗೆ `WeakRef` ಗಳನ್ನು ಸಂಗ್ರಹಿಸುತ್ತದೆ. ಇದು ಅಬ್ಸರ್ವರ್ಗಳ ಪಟ್ಟಿಯ ಸ್ವಯಂಚಾಲಿತ ಸ್ವಚ್ಛಗೊಳಿಸುವಿಕೆಯನ್ನು ನಿರ್ವಹಿಸಲು `FinalizationRegistry` ಅನ್ನು ಸಹ ಹೊಂದಿರುತ್ತದೆ.
class WeakRefSubject {
constructor() {
this.observers = new Set(); // ಸುಲಭವಾಗಿ ತೆಗೆದುಹಾಕಲು Set ಅನ್ನು ಬಳಸುವುದು
// ಫೈನಲೈಜರ್ ಕಾಲ್ಬ್ಯಾಕ್. ಇದು ನೋಂದಣಿ ಸಮಯದಲ್ಲಿ ನಾವು ಒದಗಿಸುವ ಹೆಲ್ಡ್ ವ್ಯಾಲ್ಯೂ ಅನ್ನು ಪಡೆಯುತ್ತದೆ.
// ನಮ್ಮ ಸಂದರ್ಭದಲ್ಲಿ, ಹೆಲ್ಡ್ ವ್ಯಾಲ್ಯೂ ಸ್ವತಃ WeakRef ನಿದರ್ಶನವಾಗಿರುತ್ತದೆ.
this.cleanupRegistry = new FinalizationRegistry(weakRefObserver => {
console.log('Finalizer: ಒಬ್ಬ ಅಬ್ಸರ್ವರ್ ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹಿಸಲ್ಪಟ್ಟಿದ್ದಾನೆ. ಸ್ವಚ್ಛಗೊಳಿಸಲಾಗುತ್ತಿದೆ...');
this.observers.delete(weakRefObserver);
});
}
}
ನಮ್ಮ ಅಬ್ಸರ್ವರ್ಗಳ ಪಟ್ಟಿಗೆ `Array` ಬದಲಿಗೆ `Set` ಅನ್ನು ಬಳಸುತ್ತೇವೆ. ಏಕೆಂದರೆ `Set` ನಿಂದ ಒಂದು ಐಟಂ ಅನ್ನು ಅಳಿಸುವುದು `Array` ಅನ್ನು ಫಿಲ್ಟರ್ ಮಾಡುವುದಕ್ಕಿಂತ ಹೆಚ್ಚು ಪರಿಣಾಮಕಾರಿಯಾಗಿದೆ (O(1) ಸರಾಸರಿ ಸಮಯ ಸಂಕೀರ್ಣತೆ) (O(n)), ಇದು ನಮ್ಮ ಸ್ವಚ್ಛಗೊಳಿಸುವ ತರ್ಕದಲ್ಲಿ ಉಪಯುಕ್ತವಾಗಿರುತ್ತದೆ.
ಹಂತ 2: `subscribe` ವಿಧಾನ
`subscribe` ವಿಧಾನದಲ್ಲಿ ಮ್ಯಾಜಿಕ್ ಪ್ರಾರಂಭವಾಗುತ್ತದೆ. ಒಬ್ಬ ಅಬ್ಸರ್ವರ್ ಚಂದಾದಾರರಾದಾಗ, ನಾವು ಹೀಗೆ ಮಾಡುತ್ತೇವೆ:
- ಅಬ್ಸರ್ವರ್ ಅನ್ನು ಸೂಚಿಸುವ `WeakRef` ಅನ್ನು ರಚಿಸಿ.
- ಈ `WeakRef` ಅನ್ನು ನಮ್ಮ `observers` ಸೆಟ್ಗೆ ಸೇರಿಸಿ.
- ಹೊಸದಾಗಿ ರಚಿಸಲಾದ `WeakRef` ಅನ್ನು `heldValue` ಆಗಿ ಬಳಸಿ, ಮೂಲ ಅಬ್ಸರ್ವರ್ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ನಮ್ಮ `FinalizationRegistry` ನೊಂದಿಗೆ ನೋಂದಾಯಿಸಿ.
// WeakRefSubject ವರ್ಗದೊಳಗೆ...
subscribe(observer) {
// ಈ ಉಲ್ಲೇಖದೊಂದಿಗೆ ಒಬ್ಬ ಅಬ್ಸರ್ವರ್ ಈಗಾಗಲೇ ಅಸ್ತಿತ್ವದಲ್ಲಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ
for (const ref of this.observers) {
if (ref.deref() === observer) {
console.warn('ಅಬ್ಸರ್ವರ್ ಈಗಾಗಲೇ ಚಂದಾದಾರರಾಗಿದ್ದಾರೆ.');
return;
}
}
const weakRefObserver = new WeakRef(observer);
this.observers.add(weakRefObserver);
// ಮೂಲ ಅಬ್ಸರ್ವರ್ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ನೋಂದಾಯಿಸಿ. ಅದನ್ನು ಸಂಗ್ರಹಿಸಿದಾಗ,
// ಫೈನಲೈಜರ್ ಅನ್ನು `weakRefObserver` ಅನ್ನು ಆರ್ಗ್ಯುಮೆಂಟ್ ಆಗಿ ಕರೆ ಮಾಡಲಾಗುತ್ತದೆ.
this.cleanupRegistry.register(observer, weakRefObserver);
console.log('ಒಬ್ಬ ಅಬ್ಸರ್ವರ್ ಚಂದಾದಾರರಾಗಿದ್ದಾರೆ.');
}
ಈ ಸೆಟಪ್ ಒಂದು ಬುದ್ಧಿವಂತ ಲೂಪ್ ಅನ್ನು ರಚಿಸುತ್ತದೆ: ಸಬ್ಜೆಕ್ಟ್ ಅಬ್ಸರ್ವರ್ಗೆ ದುರ್ಬಲ ಉಲ್ಲೇಖವನ್ನು ಹೊಂದಿರುತ್ತದೆ. ರಿಜಿಸ್ಟ್ರಿ ಅಬ್ಸರ್ವರ್ ಅನ್ನು (ಆಂತರಿಕವಾಗಿ) ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹಿಸುವವರೆಗೆ ಬಲವಾದ ಉಲ್ಲೇಖವನ್ನು ಹೊಂದಿರುತ್ತದೆ. ಒಮ್ಮೆ ಸಂಗ್ರಹಿಸಿದ ನಂತರ, ರಿಜಿಸ್ಟ್ರಿಯ ಕಾಲ್ಬ್ಯಾಕ್ ದುರ್ಬಲ ಉಲ್ಲೇಖದ ನಿದರ್ಶನದೊಂದಿಗೆ ಪ್ರಚೋದಿಸಲ್ಪಡುತ್ತದೆ, ಅದನ್ನು ನಾವು ನಮ್ಮ `observers` ಸೆಟ್ ಅನ್ನು ಸ್ವಚ್ಛಗೊಳಿಸಲು ಬಳಸಬಹುದು.
ಹಂತ 3: `unsubscribe` ವಿಧಾನ
ಸ್ವಯಂಚಾಲಿತ ಸ್ವಚ್ಛಗೊಳಿಸುವಿಕೆಯೊಂದಿಗೆ ಸಹ, ನಿರ್ದಿಷ್ಟ ತೆಗೆದುಹಾಕುವಿಕೆ ಅಗತ್ಯವಿರುವ ಸಂದರ್ಭಗಳಲ್ಲಿ ನಾವು ಇನ್ನೂ ಹಸ್ತಚಾಲಿತ `unsubscribe` ವಿಧಾನವನ್ನು ಒದಗಿಸಬೇಕು. ಈ ವಿಧಾನವು ನಮ್ಮ ಸೆಟ್ನಲ್ಲಿ ಸರಿಯಾದ `WeakRef` ಅನ್ನು ಕಂಡುಹಿಡಿಯಬೇಕು, ಪ್ರತಿಯೊಂದನ್ನು ಡಿರೆಫೆರೆನ್ಸ್ ಮಾಡುವ ಮೂಲಕ ಮತ್ತು ನಾವು ತೆಗೆದುಹಾಕಲು ಬಯಸುವ ಅಬ್ಸರ್ವರ್ಗೆ ಹೋಲಿಸುವ ಮೂಲಕ.
// WeakRefSubject ವರ್ಗದೊಳಗೆ...
unsubscribe(observer) {
let refToRemove = null;
for (const weakRef of this.observers) {
if (weakRef.deref() === observer) {
refToRemove = weakRef;
break;
}
}
if (refToRemove) {
this.observers.delete(refToRemove);
// ಮುಖ್ಯ: ನಾವು ಫೈನಲೈಜರ್ನಿಂದ ಅನ್ರಿಜಿಸ್ಟರ್ ಮಾಡಬೇಕು
// ಕಾಲ್ಬ್ಯಾಕ್ ನಂತರ ಅನಗತ್ಯವಾಗಿ ರನ್ ಆಗುವುದನ್ನು ತಡೆಯಲು.
this.cleanupRegistry.unregister(observer);
console.log('ಒಬ್ಬ ಅಬ್ಸರ್ವರ್ ಹಸ್ತಚಾಲಿತವಾಗಿ ಚಂದಾದಾರಿಕೆಯನ್ನು ರದ್ದುಗೊಳಿಸಿದ್ದಾರೆ.');
}
}
ಹಂತ 4: `notify` ವಿಧಾನ
`notify` ವಿಧಾನವು ನಮ್ಮ `WeakRef` ಗಳ ಸೆಟ್ ಮೂಲಕ ಪುನರಾವರ್ತಿಸುತ್ತದೆ. ಪ್ರತಿಯೊಂದಕ್ಕೂ, ಅದು ನಿಜವಾದ ಅಬ್ಸರ್ವರ್ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಪಡೆಯಲು `deref()` ಮಾಡಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ. `deref()` ಯಶಸ್ವಿಯಾದರೆ, ಅಬ್ಸರ್ವರ್ ಇನ್ನೂ ಜೀವಂತವಾಗಿದೆ ಎಂದರ್ಥ, ಮತ್ತು ನಾವು ಅದರ `update` ವಿಧಾನವನ್ನು ಕರೆಯಬಹುದು. ಅದು `undefined` ಅನ್ನು ಹಿಂತಿರುಗಿಸಿದರೆ, ಅಬ್ಸರ್ವರ್ ಅನ್ನು ಸಂಗ್ರಹಿಸಲಾಗಿದೆ ಎಂದರ್ಥ, ಮತ್ತು ನಾವು ಅದನ್ನು ಸರಳವಾಗಿ ನಿರ್ಲಕ್ಷಿಸಬಹುದು. `FinalizationRegistry` ಅಂತಿಮವಾಗಿ ತನ್ನ `WeakRef` ಅನ್ನು ಸೆಟ್ನಿಂದ ತೆಗೆದುಹಾಕುತ್ತದೆ.
// WeakRefSubject ವರ್ಗದೊಳಗೆ...
notify(data) {
console.log('ಅಬ್ಸರ್ವರ್ಗಳಿಗೆ ತಿಳಿಸಲಾಗುತ್ತಿದೆ...');
for (const weakRefObserver of this.observers) {
const observer = weakRefObserver.deref();
if (observer) {
// ಅಬ್ಸರ್ವರ್ ಇನ್ನೂ ಜೀವಂತವಾಗಿದೆ
observer.update(data);
} else {
// ಅಬ್ಸರ್ವರ್ ಅನ್ನು ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹಿಸಲಾಗಿದೆ.
// FinalizationRegistry ಈ weakRef ಅನ್ನು ಸೆಟ್ನಿಂದ ತೆಗೆದುಹಾಕುವುದನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ.
console.log('ನೋಟಿಫಿಕೇಶನ್ ಸಮಯದಲ್ಲಿ ಸತ್ತ ಅಬ್ಸರ್ವರ್ ಉಲ್ಲೇಖ ಕಂಡುಬಂದಿದೆ.');
}
}
}
ಎಲ್ಲವನ್ನೂ ಒಟ್ಟಿಗೆ ಸೇರಿಸುವುದು: ಒಂದು ಪ್ರಾಯೋಗಿಕ ಉದಾಹರಣೆ
ನಮ್ಮ UI ಕಾಂಪೊನೆಂಟ್ ಸನ್ನಿವೇಶವನ್ನು ಮರುಪರಿಶೀಲಿಸೋಣ, ಆದರೆ ಈ ಬಾರಿ ನಮ್ಮ ಹೊಸ `WeakRefSubject` ಅನ್ನು ಬಳಸಿಕೊಂಡು. ಸರಳತೆಗಾಗಿ ನಾವು ಹಿಂದಿನ `Observer` ವರ್ಗವನ್ನೇ ಬಳಸುತ್ತೇವೆ.
// ಅದೇ ಸರಳ ಅಬ್ಸರ್ವರ್ ವರ್ಗ
class Observer {
constructor(name) {
this.name = name;
}
update(data) {
console.log(`${this.name} received data: ${data}`);
}
}
ಈಗ, ಜಾಗತಿಕ ಡೇಟಾ ಸೇವೆಯನ್ನು ರಚಿಸೋಣ ಮತ್ತು ತಾತ್ಕಾಲಿಕ UI ವಿಜೆಟ್ ಅನ್ನು ಅನುಕರಿಸೋಣ.
const globalDataService = new WeakRefSubject();
function createAndDestroyWidget() {
console.log('--- ಹೊಸ ವಿಜೆಟ್ ಅನ್ನು ರಚಿಸಲಾಗುತ್ತಿದೆ ಮತ್ತು ಚಂದಾದಾರರಾಗಲಾಗುತ್ತಿದೆ ---');
let chartWidget = new Observer('RealTimeChartWidget');
globalDataService.subscribe(chartWidget);
// ವಿಜೆಟ್ ಈಗ ಸಕ್ರಿಯವಾಗಿದೆ ಮತ್ತು ನೋಟಿಫಿಕೇಶನ್ಗಳನ್ನು ಸ್ವೀಕರಿಸುತ್ತದೆ
globalDataService.notify({ price: 100 });
console.log('--- ವಿಜೆಟ್ ಅನ್ನು ನಾಶಪಡಿಸಲಾಗುತ್ತಿದೆ (ನಮ್ಮ ಉಲ್ಲೇಖವನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲಾಗುತ್ತಿದೆ) ---');
// ನಾವು ವಿಜೆಟ್ನೊಂದಿಗೆ ಕೆಲಸ ಮುಗಿಸಿದ್ದೇವೆ. ನಮ್ಮ ಉಲ್ಲೇಖವನ್ನು null ಗೆ ಹೊಂದಿಸುತ್ತೇವೆ.
// ನಾವು unsubscribe() ಅನ್ನು ಕರೆಯಬೇಕಾಗಿಲ್ಲ.
chartWidget = null;
}
createAndDestroyWidget();
console.log('--- ವಿಜೆಟ್ ನಾಶವಾದ ನಂತರ, ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹಣೆಗಿಂತ ಮೊದಲು ---');
globalDataService.notify({ price: 105 });
`createAndDestroyWidget()` ಅನ್ನು ರನ್ ಮಾಡಿದ ನಂತರ, `chartWidget` ಆಬ್ಜೆಕ್ಟ್ ಈಗ ನಮ್ಮ `globalDataService` ನೊಳಗಿನ `WeakRef` ನಿಂದ ಮಾತ್ರ ಉಲ್ಲೇಖಿಸಲ್ಪಟ್ಟಿದೆ. ಇದು ದುರ್ಬಲ ಉಲ್ಲೇಖವಾಗಿರುವುದರಿಂದ, ಆಬ್ಜೆಕ್ಟ್ ಈಗ ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹಣೆಗೆ ಅರ್ಹವಾಗಿದೆ.
ಗಾರ್ಬೇಜ್ ಕಲೆಕ್ಟರ್ ಅಂತಿಮವಾಗಿ ರನ್ ಆದಾಗ (ಅದನ್ನು ನಾವು ಊಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ), ಎರಡು ವಿಷಯಗಳು ಸಂಭವಿಸುತ್ತವೆ:
- `chartWidget` ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಮೆಮೊರಿಯಿಂದ ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ.
- ನಮ್ಮ `FinalizationRegistry` ಯ ಕಾಲ್ಬ್ಯಾಕ್ ಪ್ರಚೋದಿಸಲ್ಪಡುತ್ತದೆ, ಅದು ಈಗ ಸತ್ತ `WeakRef` ಅನ್ನು `globalDataService.observers` ಸೆಟ್ನಿಂದ ತೆಗೆದುಹಾಕುತ್ತದೆ.
ಗಾರ್ಬೇಜ್ ಕಲೆಕ್ಟರ್ ರನ್ ಆದ ನಂತರ ನಾವು ಮತ್ತೆ `notify` ಅನ್ನು ಕರೆದರೆ, `deref()` ಕರೆ `undefined` ಅನ್ನು ಹಿಂತಿರುಗಿಸುತ್ತದೆ, ಸತ್ತ ಅಬ್ಸರ್ವರ್ ಅನ್ನು ಸ್ಕಿಪ್ ಮಾಡಲಾಗುತ್ತದೆ ಮತ್ತು ಯಾವುದೇ ಮೆಮೊರಿ ಸೋರಿಕೆಗಳಿಲ್ಲದೆ ಅಪ್ಲಿಕೇಶನ್ ಪರಿಣಾಮಕಾರಿಯಾಗಿ ರನ್ ಆಗುವುದನ್ನು ಮುಂದುವರಿಸುತ್ತದೆ. ನಾವು ಅಬ್ಸರ್ವರ್ನ ಜೀವಿತಾವಧಿಯನ್ನು ಸಬ್ಜೆಕ್ಟ್ನಿಂದ ಯಶಸ್ವಿಯಾಗಿ ಡಿಕಪಲ್ ಮಾಡಿದ್ದೇವೆ.
`WeakRefObserver` ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ಯಾವಾಗ ಬಳಸಬೇಕು (ಮತ್ತು ಯಾವಾಗ ತಪ್ಪಿಸಬೇಕು)
ಈ ಪ್ಯಾಟರ್ನ್ ಶಕ್ತಿಶಾಲಿಯಾಗಿದೆ, ಆದರೆ ಇದು ಎಲ್ಲ ಸಮಸ್ಯೆಗಳಿಗೂ ಪರಿಹಾರವಲ್ಲ. ಇದು ಸಂಕೀರ್ಣತೆಯನ್ನು ಪರಿಚಯಿಸುತ್ತದೆ ಮತ್ತು ಅನಿಶ್ಚಿತ ನಡವಳಿಕೆಯನ್ನು ಅವಲಂಬಿಸಿದೆ. ಇದು ಕೆಲಸಕ್ಕೆ ಸರಿಯಾದ ಸಾಧನವಾಗಿದ್ದಾಗ ತಿಳಿಯುವುದು ನಿರ್ಣಾಯಕವಾಗಿದೆ.
ಆದರ್ಶ ಬಳಕೆಯ ಸಂದರ್ಭಗಳು
- ದೀರ್ಘಕಾಲಿಕ ಸಬ್ಜೆಕ್ಟ್ಗಳು ಮತ್ತು ಅಲ್ಪಕಾಲಿಕ ಅಬ್ಸರ್ವರ್ಗಳು: ಇದು ಸಾಂಪ್ರದಾಯಿಕ ಬಳಕೆಯ ಸಂದರ್ಭವಾಗಿದೆ. ಸಂಪೂರ್ಣ ಅಪ್ಲಿಕೇಶನ್ ಜೀವಿತಾವಧಿಯಲ್ಲಿ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಜಾಗತಿಕ ಸೇವೆ, ಡೇಟಾ ಸ್ಟೋರ್ ಅಥವಾ ಕ್ಯಾಶ್ (ಸಬ್ಜೆಕ್ಟ್), ಆದರೆ ಹಲವಾರು UI ಘಟಕಗಳು, ತಾತ್ಕಾಲಿಕ ವರ್ಕರ್ಗಳು ಅಥವಾ ಪ್ಲಗಿನ್ಗಳು (ಅಬ್ಸರ್ವರ್ಗಳು) ಆಗಾಗ್ಗೆ ರಚಿಸಲ್ಪಟ್ಟ ಮತ್ತು ನಾಶಪಡಿಸಲ್ಪಡುತ್ತವೆ.
- ಕ್ಯಾಚಿಂಗ್ ಕಾರ್ಯವಿಧಾನಗಳು: ಒಂದು ಸಂಕೀರ್ಣ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಕೆಲವು ಲೆಕ್ಕಾಚಾರದ ಫಲಿತಾಂಶಕ್ಕೆ ನಕ್ಷೆ ಮಾಡುವ ಕ್ಯಾಶ್ ಅನ್ನು ಊಹಿಸಿ. ನೀವು ಕೀ ಆಬ್ಜೆಕ್ಟ್ಗಾಗಿ `WeakRef` ಅನ್ನು ಬಳಸಬಹುದು. ಮೂಲ ಆಬ್ಜೆಕ್ಟ್ ಅನ್ನು ಅಪ್ಲಿಕೇಶನ್ನ ಉಳಿದ ಭಾಗದಿಂದ ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹಿಸಿದರೆ, `FinalizationRegistry` ನಿಮ್ಮ ಕ್ಯಾಶ್ನಲ್ಲಿನ ಅನುಗುಣವಾದ ಪ್ರವೇಶವನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸ್ವಚ್ಛಗೊಳಿಸಬಹುದು, ಮೆಮೊರಿ bloat ಅನ್ನು ತಡೆಯುತ್ತದೆ.
- ಪ್ಲಗಿನ್ ಮತ್ತು ವಿಸ್ತರಣೆ ಆರ್ಕಿಟೆಕ್ಚರ್ಗಳು: ನೀವು ಮೂರನೇ ವ್ಯಕ್ತಿಯ ಮಾಡ್ಯೂಲ್ಗಳಿಗೆ ಈವೆಂಟ್ಗಳಿಗೆ ಚಂದಾದಾರರಾಗಲು ಅನುಮತಿಸುವ ಪ್ರಮುಖ ವ್ಯವಸ್ಥೆಯನ್ನು ನಿರ್ಮಿಸುತ್ತಿದ್ದರೆ, `WeakRefObserver` ಅನ್ನು ಬಳಸುವುದು ಸ್ಥಿತಿಸ್ಥಾಪಕತ್ವದ ಪದರವನ್ನು ಸೇರಿಸುತ್ತದೆ. ಇದು ಅನ್ಸಬ್ಸ್ಕ್ರೈಬ್ ಮಾಡಲು ಮರೆತ poor-written ಪ್ಲಗಿನ್ ನಿಮ್ಮ ಪ್ರಮುಖ ಅಪ್ಲಿಕೇಶನ್ನಲ್ಲಿ ಮೆಮೊರಿ ಸೋರಿಕೆಗೆ ಕಾರಣವಾಗುವುದನ್ನು ತಡೆಯುತ್ತದೆ.
- ಡೇಟಾವನ್ನು DOM ಎಲಿಮೆಂಟ್ಗಳಿಗೆ ನಕ್ಷೆ ಮಾಡುವುದು: ಘೋಷಣಾತ್ಮಕ ಫ್ರೇಮ್ವರ್ಕ್ ಇಲ್ಲದ ಸನ್ನಿವೇಶಗಳಲ್ಲಿ, ನೀವು ಕೆಲವು ಡೇಟಾವನ್ನು DOM ಎಲಿಮೆಂಟ್ನೊಂದಿಗೆ ಸಂಯೋಜಿಸಲು ಬಯಸಬಹುದು. ನೀವು ಇದನ್ನು DOM ಎಲಿಮೆಂಟ್ ಅನ್ನು ಕೀಯಾಗಿ ಹೊಂದಿರುವ ನಕ್ಷೆಯಲ್ಲಿ ಸಂಗ್ರಹಿಸಿದರೆ, ಎಲಿಮೆಂಟ್ ಅನ್ನು DOM ನಿಂದ ತೆಗೆದುಹಾಕಿದರೂ ನಿಮ್ಮ ನಕ್ಷೆಯಲ್ಲಿ ಇದ್ದರೆ ನೀವು ಮೆಮೊರಿ ಸೋರಿಕೆಯನ್ನು ರಚಿಸಬಹುದು. ಇಲ್ಲಿ `WeakMap` ಉತ್ತಮ ಆಯ್ಕೆಯಾಗಿದೆ, ಆದರೆ ತತ್ವವು ಒಂದೇ ಆಗಿರುತ್ತದೆ: ಡೇಟಾದ ಜೀವಿತಾವಧಿಯು ಎಲಿಮೆಂಟ್ನ ಜೀವಿತಾವಧಿಗೆ ಸಂಬಂಧಿಸಿರಬೇಕು, ಇನ್ನೊಂದು ರೀತಿಯಲ್ಲಿ ಅಲ್ಲ.
ಕ್ಲಾಸಿಕ್ ಅಬ್ಸರ್ವರ್ನೊಂದಿಗೆ ಯಾವಾಗ ಅಂಟಿಕೊಳ್ಳಬೇಕು
- ತೀವ್ರವಾಗಿ ಜೋಡಿಸಲಾದ ಜೀವಿತಾವಧಿಗಳು: ಸಬ್ಜೆಕ್ಟ್ ಮತ್ತು ಅದರ ಅಬ್ಸರ್ವರ್ಗಳನ್ನು ಯಾವಾಗಲೂ ಒಟ್ಟಿಗೆ ಅಥವಾ ಒಂದೇ ವ್ಯಾಪ್ತಿಯಲ್ಲಿ ರಚಿಸಿ ಮತ್ತು ನಾಶಪಡಿಸಿದರೆ, `WeakRef` ನ ಓವರ್ಹೆಡ್ ಮತ್ತು ಸಂಕೀರ್ಣತೆ ಅನಗತ್ಯವಾಗಿರುತ್ತದೆ. ಸರಳ, ಸ್ಪಷ್ಟವಾದ `unsubscribe()` ಕರೆ ಹೆಚ್ಚು ಓದಬಲ್ಲ ಮತ್ತು ಊಹಿಸಬಹುದಾಗಿದೆ.
- ಕಾರ್ಯಕ್ಷಮತೆ-ನಿರ್ಣಾಯಕ ಹಾಟ್ ಪಾತ್ಗಳು: `deref()` ವಿಧಾನವು ಸಣ್ಣ ಆದರೆ ಶೂನ್ಯವಲ್ಲದ ಕಾರ್ಯಕ್ಷಮತೆ ವೆಚ್ಚವನ್ನು ಹೊಂದಿದೆ. ನೀವು ಸೆಕೆಂಡಿಗೆ ನೂರಾರು ಬಾರಿ ಸಾವಿರಾರು ಅಬ್ಸರ್ವರ್ಗಳಿಗೆ ತಿಳಿಸುತ್ತಿದ್ದರೆ (ಉದಾ. ಒಂದು ಗೇಮ್ ಲೂಪ್ ಅಥವಾ ಹೈ-ಫ್ರೀಕ್ವೆನ್ಸಿ ಡೇಟಾ ದೃಶ್ಯೀಕರಣದಲ್ಲಿ), ನೇರ ಉಲ್ಲೇಖಗಳೊಂದಿಗೆ ಕ್ಲಾಸಿಕ್ ಅನುಷ್ಠಾನವು ವೇಗವಾಗಿರುತ್ತದೆ.
- ಸರಳ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ಸ್ಕ್ರಿಪ್ಟ್ಗಳು: ಅಪ್ಲಿಕೇಶನ್ ಜೀವಿತಾವಧಿಯು ಚಿಕ್ಕದಾಗಿದ್ದು ಮತ್ತು ಮೆಮೊರಿ ನಿರ್ವಹಣೆಯು ಗಮನಾರ್ಹ ಕಾಳಜಿಯಾಗಿಲ್ಲದ ಸಣ್ಣ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಅಥವಾ ಸ್ಕ್ರಿಪ್ಟ್ಗಳಿಗೆ, ಕ್ಲಾಸಿಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಮತ್ತು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಲು ಸರಳವಾಗಿದೆ. ಅಗತ್ಯವಿಲ್ಲದ ಕಡೆ ಸಂಕೀರ್ಣತೆಯನ್ನು ಸೇರಿಸಬೇಡಿ.
- ನಿರ್ಣಾಯಕ ಸ್ವಚ್ಛಗೊಳಿಸುವಿಕೆ ಅಗತ್ಯವಿದ್ದಾಗ: ಅಬ್ಸರ್ವರ್ ಅನ್ನು ಬೇರ್ಪಡಿಸಿದ ನಿಖರ ಕ್ಷಣದಲ್ಲಿ ನೀವು ಒಂದು ಕ್ರಿಯೆಯನ್ನು ನಿರ್ವಹಿಸಬೇಕಾದರೆ (ಉದಾ. ಕೌಂಟರ್ ಅನ್ನು ನವೀಕರಿಸುವುದು, ನಿರ್ದಿಷ್ಟ ಹಾರ್ಡ್ವೇರ್ ಸಂಪನ್ಮೂಲವನ್ನು ಬಿಡುಗಡೆ ಮಾಡುವುದು), ನೀವು ಹಸ್ತಚಾಲಿತ `unsubscribe()` ವಿಧಾನವನ್ನು ಖಂಡಿತವಾಗಿಯೂ ಬಳಸಬೇಕು. `FinalizationRegistry` ಯ ಅನಿಶ್ಚಿತ ಸ್ವರೂಪವು ಊಹಿಸಬಹುದಾದಂತೆ ಕಾರ್ಯಗತಗೊಳಿಸಬೇಕಾದ ತರ್ಕಕ್ಕೆ ಸೂಕ್ತವಲ್ಲ.
ಸಾಫ್ಟ್ವೇರ್ ಆರ್ಕಿಟೆಕ್ಚರ್ಗಾಗಿ ವ್ಯಾಪಕ ಪರಿಣಾಮಗಳು
ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ನಂತಹ ಉನ್ನತ-ಮಟ್ಟದ ಭಾಷೆಗೆ ದುರ್ಬಲ ಉಲ್ಲೇಖಗಳನ್ನು ಪರಿಚಯಿಸುವುದು ಪ್ಲಾಟ್ಫಾರ್ಮ್ನ ಪರಿಪಕ್ವತೆಯನ್ನು ಸೂಚಿಸುತ್ತದೆ. ಇದು ಡೆವಲಪರ್ಗಳಿಗೆ ಹೆಚ್ಚು ಅತ್ಯಾಧುನಿಕ ಮತ್ತು ಸ್ಥಿತಿಸ್ಥಾಪಕ ವ್ಯವಸ್ಥೆಗಳನ್ನು ನಿರ್ಮಿಸಲು ಅನುಮತಿಸುತ್ತದೆ, ವಿಶೇಷವಾಗಿ ದೀರ್ಘಕಾಲಿಕ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗಾಗಿ. ಈ ಮಾದರಿಯು ವಾಸ್ತುಶಿಲ್ಪದ ಚಿಂತನೆಯಲ್ಲಿ ಬದಲಾವಣೆಯನ್ನು ಪ್ರೋತ್ಸಾಹಿಸುತ್ತದೆ:
- ನಿಜವಾದ ಡಿಕಪ್ಲಿಂಗ್: ಇದು ಕೇವಲ ಇಂಟರ್ಫೇಸ್ನ ಆಚೆಗೆ ಹೋಗುವ ಡಿಕಪ್ಲಿಂಗ್ ಮಟ್ಟವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ. ನಾವು ಈಗ ಘಟಕಗಳ ಜೀವಿತಾವಧಿಗಳನ್ನು ಡಿಕಪಲ್ ಮಾಡಬಹುದು. ಅದರ ಅಬ್ಸರ್ವರ್ಗಳನ್ನು ಯಾವಾಗ ರಚಿಸಲಾಗಿದೆ ಅಥವಾ ನಾಶಪಡಿಸಲಾಗುತ್ತದೆ ಎಂಬುದರ ಕುರಿತು ಸಬ್ಜೆಕ್ಟ್ಗೆ ಇನ್ನು ಮುಂದೆ ಏನೂ ತಿಳಿದಿರುವುದಿಲ್ಲ.
- ವಿನ್ಯಾಸದ ಮೂಲಕ ಸ್ಥಿತಿಸ್ಥಾಪಕತ್ವ: ಇದು ಪ್ರೋಗ್ರಾಮರ್ ದೋಷಕ್ಕೆ ಹೆಚ್ಚು ಸ್ಥಿತಿಸ್ಥಾಪಕ ವ್ಯವಸ್ಥೆಗಳನ್ನು ನಿರ್ಮಿಸಲು ಸಹಾಯ ಮಾಡುತ್ತದೆ. ಮರೆತುಹೋದ `unsubscribe()` ಕರೆ ಒಂದು ಸಾಮಾನ್ಯ ಬಗ್ ಆಗಿದ್ದು, ಅದನ್ನು ಪತ್ತೆಹಚ್ಚಲು ಕಷ್ಟವಾಗಬಹುದು. ಈ ಮಾದರಿಯು ಆ ಸಂಪೂರ್ಣ ವರ್ಗದ ದೋಷಗಳನ್ನು ತಗ್ಗಿಸುತ್ತದೆ.
- ಫ್ರೇಮ್ವರ್ಕ್ ಮತ್ತು ಲೈಬ್ರರಿ ಲೇಖಕರನ್ನು ಸಕ್ರಿಯಗೊಳಿಸುವುದು: ಇತರ ಡೆವಲಪರ್ಗಳಿಗಾಗಿ ಫ್ರೇಮ್ವರ್ಕ್ಗಳು, ಲೈಬ್ರರಿಗಳು ಅಥವಾ ಪ್ಲಾಟ್ಫಾರ್ಮ್ಗಳನ್ನು ನಿರ್ಮಿಸುವವರಿಗೆ, ಈ ಉಪಕರಣಗಳು ಅಮೂಲ್ಯವಾಗಿವೆ. ಅವು ಲೈಬ್ರರಿಯ ಗ್ರಾಹಕರಿಂದ ದುರುಪಯೋಗಕ್ಕೆ ಕಡಿಮೆ ಒಳಗಾಗುವ ದೃಢವಾದ API ಗಳನ್ನು ರಚಿಸಲು ಅನುಮತಿಸುತ್ತದೆ, ಇದು ಒಟ್ಟಾರೆ ಹೆಚ್ಚು ಸ್ಥಿರವಾದ ಅಪ್ಲಿಕೇಶನ್ಗಳಿಗೆ ಕಾರಣವಾಗುತ್ತದೆ.
ತೀರ್ಮಾನ: ಆಧುನಿಕ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಡೆವಲಪರ್ಗಾಗಿ ಶಕ್ತಿಶಾಲಿ ಸಾಧನ
ಕ್ಲಾಸಿಕ್ ಅಬ್ಸರ್ವರ್ ಪ್ಯಾಟರ್ನ್ ಸಾಫ್ಟ್ವೇರ್ ವಿನ್ಯಾಸದ ಮೂಲಭೂತ ನಿರ್ಮಾಣ ಬ್ಲಾಕ್ ಆಗಿದೆ, ಆದರೆ ಬಲವಾದ ಉಲ್ಲೇಖಗಳ ಮೇಲಿನ ಅದರ ಅವಲಂಬನೆಯು ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಅಪ್ಲಿಕೇಶನ್ಗಳಲ್ಲಿ ಸೂಕ್ಷ್ಮ ಮತ್ತು ನಿರಾಶಾದಾಯಕ ಮೆಮೊರಿ ಸೋರಿಕೆಗಳ ಮೂಲವಾಗಿದೆ. ES2021 ರಲ್ಲಿ `WeakRef` ಮತ್ತು `FinalizationRegistry` ಆಗಮನದೊಂದಿಗೆ, ಈ ಮಿತಿಯನ್ನು ನಿವಾರಿಸಲು ಈಗ ನಮ್ಮ ಬಳಿ ಸಾಧನಗಳಿವೆ.
ಉಳಿದಿರುವ ಉಲ್ಲೇಖಗಳ ಮೂಲಭೂತ ಸಮಸ್ಯೆಯನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳುವುದರಿಂದ ಹಿಡಿದು ಸಂಪೂರ್ಣ, ಮೆಮೊರಿ-ಅವೇರ್ `WeakRefSubject` ಅನ್ನು ಮೊದಲಿನಿಂದ ನಿರ್ಮಿಸುವವರೆಗೆ ನಾವು ಪ್ರಯಾಣಿಸಿದ್ದೇವೆ. ಆಬ್ಜೆಕ್ಟ್ಗಳನ್ನು 'ಅಬ್ಸರ್ವ್' ಮಾಡಿದಾಗಲೂ ಗಾರ್ಬೇಜ್ ಸಂಗ್ರಹಿಸಲು `WeakRef` ಹೇಗೆ ಅನುಮತಿಸುತ್ತದೆ ಮತ್ತು ನಮ್ಮ ಅಬ್ಸರ್ವರ್ ಪಟ್ಟಿಯನ್ನು ಶುದ್ಧವಾಗಿಡಲು `FinalizationRegistry` ಹೇಗೆ ಸ್ವಯಂಚಾಲಿತ ಸ್ವಚ್ಛಗೊಳಿಸುವ ಕಾರ್ಯವಿಧಾನವನ್ನು ಒದಗಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ನಾವು ನೋಡಿದ್ದೇವೆ.
ಆದಾಗ್ಯೂ, ದೊಡ್ಡ ಶಕ್ತಿಯೊಂದಿಗೆ ದೊಡ್ಡ ಜವಾಬ್ದಾರಿ ಬರುತ್ತದೆ. ಇವುಗಳು ಸುಧಾರಿತ ವೈಶಿಷ್ಟ್ಯಗಳಾಗಿದ್ದು, ಇವುಗಳ ಅನಿಶ್ಚಿತ ಸ್ವರೂಪಕ್ಕೆ ಎಚ್ಚರಿಕೆಯ ಪರಿಗಣನೆ ಅಗತ್ಯವಿದೆ. ಅವು ಉತ್ತಮ ಅಪ್ಲಿಕೇಶನ್ ವಿನ್ಯಾಸ ಮತ್ತು ಶ್ರದ್ಧೆಯ ಜೀವಿತಾವಧಿ ನಿರ್ವಹಣೆಗೆ ಬದಲಿಯಾಗಿಲ್ಲ. ಆದರೆ ದೀರ್ಘಕಾಲಿಕ ಸೇವೆಗಳು ಮತ್ತು ಅಲ್ಪಕಾಲಿಕ ಘಟಕಗಳ ನಡುವಿನ ಸಂವಹನವನ್ನು ನಿರ್ವಹಿಸುವಂತಹ ಸರಿಯಾದ ಸಮಸ್ಯೆಗಳಿಗೆ ಅನ್ವಯಿಸಿದಾಗ, WeakRef Observer ಪ್ಯಾಟರ್ನ್ ಅಸಾಧಾರಣವಾಗಿ ಶಕ್ತಿಶಾಲಿ ತಂತ್ರವಾಗಿದೆ. ಅದನ್ನು ಕರಗತ ಮಾಡಿಕೊಳ್ಳುವ ಮೂಲಕ, ನೀವು ಹೆಚ್ಚು ದೃಢವಾದ, ಪರಿಣಾಮಕಾರಿ ಮತ್ತು ಸ್ಕೇಲೆಬಲ್ ಜಾವಾಸ್ಕ್ರಿಪ್ಟ್ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಬರೆಯಬಹುದು, ಆಧುನಿಕ, ಡೈನಾಮಿಕ್ ವೆಬ್ನ ಬೇಡಿಕೆಗಳನ್ನು ಪೂರೈಸಲು ಸಿದ್ಧರಾಗಬಹುದು.