ApgÅ«stiet JavaScript asinhronÄ konteksta atmiÅas pÄrvaldÄ«bu un optimizÄjiet konteksta dzÄ«ves ciklu, lai uzlabotu asinhrono lietojumprogrammu veiktspÄju un uzticamÄ«bu.
JavaScript asinhronÄ konteksta atmiÅas pÄrvaldÄ«ba: konteksta dzÄ«ves cikla optimizÄcija
AsinhronÄ programmÄÅ”ana ir mÅ«sdienu JavaScript izstrÄdes stÅ«rakmens, kas ļauj mums veidot atsaucÄ«gas un efektÄ«vas lietojumprogrammas. TomÄr konteksta pÄrvaldÄ«ba asinhronÄs operÄcijÄs var kļūt sarežģīta, izraisot atmiÅas noplÅ«des un veiktspÄjas problÄmas, ja ar to nerÄ«kojas uzmanÄ«gi. Å is raksts iedziļinÄs JavaScript asinhronÄ konteksta sarežģītÄ«bÄ, koncentrÄjoties uz tÄ dzÄ«ves cikla optimizÄÅ”anu robustÄm un mÄrogojamÄm lietojumprogrammÄm.
Izpratne par asinhrono kontekstu JavaScript
SinhronÄ JavaScript kodÄ kontekstu (mainÄ«gos, funkciju izsaukumus un izpildes stÄvokli) ir viegli pÄrvaldÄ«t. Kad funkcija beidz darbu, tÄs konteksts parasti tiek atbrÄ«vots, ļaujot atkritumu savÄcÄjam (garbage collector) atgÅ«t atmiÅu. TomÄr asinhronÄs operÄcijas ievieÅ” sarežģītÄ«bas slÄni. Asinhroni uzdevumi, piemÄram, datu ielÄde no API vai lietotÄja notikumu apstrÄde, ne vienmÄr tiek pabeigti nekavÄjoties. Tie bieži ietver atzvanus (callbacks), solÄ«jumus (promises) vai async/await, kas var izveidot noslÄgumus (closures) un saglabÄt atsauces uz mainÄ«gajiem apkÄrtÄjÄ tvÄrumÄ (scope). Tas var nejauÅ”i uzturÄt daļu konteksta dzÄ«vu ilgÄk, nekÄ nepiecieÅ”ams, izraisot atmiÅas noplÅ«des.
NoslÄgumu (Closures) loma
NoslÄgumiem ir izŔķiroÅ”a loma asinhronajÄ JavaScript. NoslÄgums ir funkcijas kombinÄcija, kas ir apvienota (iekļauta) ar atsaucÄm uz tÄs apkÄrtÄjo stÄvokli (leksisko vidi). Citiem vÄrdiem sakot, noslÄgums dod jums piekļuvi ÄrÄjÄs funkcijas tvÄrumam no iekÅ”ÄjÄs funkcijas. Kad asinhrona operÄcija paļaujas uz atzvanu vai solÄ«jumu, tÄ bieži izmanto noslÄgumus, lai piekļūtu mainÄ«gajiem no tÄs vecÄktvÄruma. Ja Å”ie noslÄgumi saglabÄ atsauces uz lieliem objektiem vai datu struktÅ«rÄm, kas vairs nav vajadzÄ«gas, tas var bÅ«tiski ietekmÄt atmiÅas patÄriÅu.
Apsveriet Å”o piemÄru:
function fetchData(url) {
const largeData = new Array(1000000).fill('some data'); // Simulate a large dataset
return new Promise((resolve, reject) => {
setTimeout(() => {
// Simulate fetching data from an API
const result = `Data from ${url}`; // Uses url from the outer scope
resolve(result);
}, 1000);
});
}
async function processData() {
const data = await fetchData('https://example.com/api/data');
console.log(data);
// largeData is still in scope here, even if it's not used directly
}
processData();
Å ajÄ piemÄrÄ, pat pÄc tam, kad `processData` ir reÄ£istrÄjis ielÄdÄtos datus, `largeData` paliek tvÄrumÄ noslÄguma dÄļ, ko izveidojis `setTimeout` atzvans `fetchData` ietvaros. Ja `fetchData` tiek izsaukta vairÄkas reizes, atmiÅÄ varÄtu tikt saglabÄtas vairÄkas `largeData` instances, kas potenciÄli var izraisÄ«t atmiÅas noplÅ«di.
AtmiÅas noplūžu identificÄÅ”ana asinhronajÄ JavaScript
AtmiÅas noplūžu atklÄÅ”ana asinhronajÄ JavaScript var bÅ«t sarežģīta. Å eit ir daži izplatÄ«ti rÄ«ki un metodes:
- PÄrlÅ«kprogrammas izstrÄdÄtÄju rÄ«ki: LielÄkÄ daļa mÅ«sdienu pÄrlÅ«kprogrammu nodroÅ”ina jaudÄ«gus izstrÄdÄtÄju rÄ«kus atmiÅas lietojuma profilÄÅ”anai. PiemÄram, Chrome DevTools ļauj jums veikt kaudzes momentuzÅÄmumus (heap snapshots), ierakstÄ«t atmiÅas pieŔķirÅ”anas laika skalas un identificÄt objektus, kuri netiek savÄkti atkritumos. IzmeklÄjot potenciÄlÄs noplÅ«des, pievÄrsiet uzmanÄ«bu saglabÄtajam lielumam (retained size) un konstruktoru tipiem.
- Node.js atmiÅas profilerÄtÄji: Node.js lietojumprogrammÄm varat izmantot tÄdus rÄ«kus kÄ `heapdump` un `v8-profiler`, lai uzÅemtu kaudzes momentuzÅÄmumus un analizÄtu atmiÅas lietojumu. Node.js inspektors (`node --inspect`) arÄ« nodroÅ”ina atkļūdoÅ”anas saskarni, kas lÄ«dzÄ«ga Chrome DevTools.
- VeiktspÄjas uzraudzÄ«bas rÄ«ki: Lietojumprogrammu veiktspÄjas uzraudzÄ«bas (APM) rÄ«ki, piemÄram, New Relic, Datadog un Sentry, var sniegt ieskatu par atmiÅas lietojuma tendencÄm laika gaitÄ. Å ie rÄ«ki var palÄ«dzÄt jums identificÄt modeļus un norÄdÄ«t uz koda vietÄm, kas varÄtu veicinÄt atmiÅas noplÅ«des.
- Koda pÄrskates: RegulÄras koda pÄrskates var palÄ«dzÄt identificÄt potenciÄlÄs atmiÅas pÄrvaldÄ«bas problÄmas, pirms tÄs kļūst par problÄmu. PievÄrsiet Ä«paÅ”u uzmanÄ«bu noslÄgumiem, notikumu klausÄ«tÄjiem (event listeners) un datu struktÅ«rÄm, kas tiek izmantotas asinhronÄs operÄcijÄs.
BiežÄkÄs atmiÅas noplūžu pazÄ«mes
Å eit ir dažas pazÄ«mes, kas liecina, ka jÅ«su JavaScript lietojumprogrammai varÄtu bÅ«t atmiÅas noplÅ«des:
- PakÄpenisks atmiÅas lietojuma pieaugums: Lietojumprogrammas atmiÅas patÄriÅÅ” laika gaitÄ stabili pieaug, pat ja tÄ aktÄ«vi neveic uzdevumus.
- VeiktspÄjas pasliktinÄÅ”anÄs: Lietojumprogramma kļūst lÄnÄka un mazÄk atsaucÄ«ga, jo ilgÄk tÄ darbojas.
- Bieži atkritumu savÄkÅ”anas cikli: Atkritumu savÄcÄjs darbojas biežÄk, norÄdot, ka tam ir grÅ«tÄ«bas atgÅ«t atmiÅu.
- Lietojumprogrammas avÄrijas: ÄrkÄrtÄjos gadÄ«jumos atmiÅas noplÅ«des var izraisÄ«t lietojumprogrammas avÄrijas atmiÅas trÅ«kuma kļūdu dÄļ.
AsinhronÄ konteksta dzÄ«ves cikla optimizÄÅ”ana
Tagad, kad mÄs saprotam asinhronÄ konteksta atmiÅas pÄrvaldÄ«bas izaicinÄjumus, izpÄtÄ«sim dažas stratÄÄ£ijas konteksta dzÄ«ves cikla optimizÄÅ”anai:
1. NoslÄguma tvÄruma (Closure Scope) minimizÄÅ”ana
Jo mazÄks ir noslÄguma tvÄrums, jo mazÄk atmiÅas tas patÄrÄs. Izvairieties no nevajadzÄ«gu mainÄ«go saglabÄÅ”anas noslÄgumos. TÄ vietÄ nododiet asinhronajai operÄcijai tikai tos datus, kas ir stingri nepiecieÅ”ami.
PiemÄrs:
Slikti:
function processUserData(user) {
const userData = { ...user, extraData: 'some extra info' }; // Create a new object
setTimeout(() => {
console.log(`Processing user: ${userData.name}`); // Access userData
}, 1000);
}
Å ajÄ piemÄrÄ viss `userData` objekts tiek saglabÄts noslÄgumÄ, lai gan `setTimeout` atzvanÄ tiek izmantota tikai `name` Ä«paŔība.
Labi:
function processUserData(user) {
const userData = { ...user, extraData: 'some extra info' };
const userName = userData.name; // Extract the name
setTimeout(() => {
console.log(`Processing user: ${userName}`); // Access only userName
}, 1000);
}
Å ajÄ optimizÄtajÄ versijÄ noslÄgumÄ tiek saglabÄts tikai `userName`, samazinot atmiÅas nospiedumu.
2. Ciklisko atsauÄu pÄrtraukÅ”ana
CikliskÄs atsauces rodas, kad divi vai vairÄki objekti atsaucas viens uz otru, neļaujot tos savÄkt atkritumos. TÄ var bÅ«t izplatÄ«ta problÄma asinhronajÄ JavaScript, Ä«paÅ”i strÄdÄjot ar notikumu klausÄ«tÄjiem vai sarežģītÄm datu struktÅ«rÄm.
PiemÄrs:
class MyObject {
constructor() {
this.eventListeners = [];
}
addListener(listener) {
this.eventListeners.push(listener);
}
removeListener(listener) {
this.eventListeners = this.eventListeners.filter(l => l !== listener);
}
doSomethingAsync() {
const listener = () => {
console.log('Something happened!');
this.doSomethingElse(); // Circular reference: listener references this
};
this.addListener(listener);
setTimeout(() => {
this.removeListener(listener);
}, 1000);
}
doSomethingElse() {
console.log('Doing something else.');
}
}
const myObject = new MyObject();
myObject.doSomethingAsync();
Å ajÄ piemÄrÄ `listener` funkcija `doSomethingAsync` ietvaros saglabÄ atsauci uz `this` (`MyObject` instanci). `MyObject` instance arÄ« glabÄ atsauci uz `listener` caur `eventListeners` masÄ«vu. Tas rada ciklisku atsauci, neļaujot gan `MyObject` instancei, gan `listener` tikt savÄktiem atkritumos pat pÄc `setTimeout` atzvana izpildes. Lai gan klausÄ«tÄjs tiek noÅemts no eventListeners masÄ«va, pats noslÄgums joprojÄm saglabÄ atsauci uz `this`.
RisinÄjums: PÄrtrauciet ciklisko atsauci, skaidri iestatot atsauci uz `null` vai undefined, kad tÄ vairs nav nepiecieÅ”ama.
class MyObject {
constructor() {
this.eventListeners = [];
}
addListener(listener) {
this.eventListeners.push(listener);
}
removeListener(listener) {
this.eventListeners = this.eventListeners.filter(l => l !== listener);
}
doSomethingAsync() {
let listener = () => {
console.log('Something happened!');
this.doSomethingElse();
listener = null; // Break the circular reference
};
this.addListener(listener);
setTimeout(() => {
this.removeListener(listener);
}, 1000);
}
doSomethingElse() {
console.log('Doing something else.');
}
}
const myObject = new MyObject();
myObject.doSomethingAsync();
Lai gan iepriekÅ”minÄtais risinÄjums varÄtu Ŕķist, ka tas pÄrtrauc ciklisko atsauci, klausÄ«tÄjs `setTimeout` ietvaros joprojÄm atsaucas uz sÄkotnÄjo `listener` funkciju, kas savukÄrt atsaucas uz `this`. UzticamÄks risinÄjums ir izvairÄ«ties no `this` tieÅ”as saglabÄÅ”anas klausÄ«tÄjÄ.
class MyObject {
constructor() {
this.eventListeners = [];
}
addListener(listener) {
this.eventListeners.push(listener);
}
removeListener(listener) {
this.eventListeners = this.eventListeners.filter(l => l !== listener);
}
doSomethingAsync() {
const self = this; // Capture 'this' in a separate variable
const listener = () => {
console.log('Something happened!');
self.doSomethingElse(); // Use the captured 'self'
};
this.addListener(listener);
setTimeout(() => {
this.removeListener(listener);
}, 1000);
}
doSomethingElse() {
console.log('Doing something else.');
}
}
const myObject = new MyObject();
myObject.doSomethingAsync();
Tas joprojÄm pilnÄ«bÄ neatrisina problÄmu, ja notikumu klausÄ«tÄjs paliek pievienots ilgu laiku. VisuzticamÄkÄ pieeja ir pilnÄ«bÄ izvairÄ«ties no noslÄgumiem, kas tieÅ”i atsaucas uz `MyObject` instanci, un izmantot notikumu izplatīŔanas mehÄnismu.
3. Notikumu klausÄ«tÄju (Event Listeners) pÄrvaldÄ«ba
Notikumu klausÄ«tÄji ir izplatÄ«ts atmiÅas noplūžu avots, ja tie netiek pareizi noÅemti. Pievienojot notikumu klausÄ«tÄju elementam vai objektam, klausÄ«tÄjs paliek aktÄ«vs, lÄ«dz tas tiek skaidri noÅemts vai elements/objekts tiek iznÄ«cinÄts. Ja aizmirstat noÅemt klausÄ«tÄjus, tie laika gaitÄ var uzkrÄties, patÄrÄjot atmiÅu un potenciÄli radot veiktspÄjas problÄmas.
PiemÄrs:
const button = document.getElementById('myButton');
function handleClick() {
console.log('Button clicked!');
}
button.addEventListener('click', handleClick);
// PROBLEM: The event listener is never removed!
RisinÄjums: VienmÄr noÅemiet notikumu klausÄ«tÄjus, kad tie vairs nav nepiecieÅ”ami.
const button = document.getElementById('myButton');
function handleClick() {
console.log('Button clicked!');
button.removeEventListener('click', handleClick); // Remove the listener
}
button.addEventListener('click', handleClick);
// Alternatively, remove the listener after a certain condition:
setTimeout(() => {
button.removeEventListener('click', handleClick);
}, 5000);
Apsveriet iespÄju izmantot `WeakMap`, lai uzglabÄtu notikumu klausÄ«tÄjus, ja jums ir nepiecieÅ”ams saistÄ«t datus ar DOM elementiem, neaizkavÄjot Å”o elementu atkritumu savÄkÅ”anu.
4. `WeakRef` un `FinalizationRegistry` izmantoÅ”ana (padziļinÄti)
SarežģītÄkos gadÄ«jumos varat izmantot `WeakRef` un `FinalizationRegistry`, lai uzraudzÄ«tu objektu dzÄ«ves ciklu un veiktu tÄ«rīŔanas uzdevumus, kad objekti tiek savÄkti atkritumos. `WeakRef` ļauj turÄt atsauci uz objektu, neaizkavÄjot tÄ savÄkÅ”anu atkritumos. `FinalizationRegistry` ļauj reÄ£istrÄt atzvanu, kas tiks izpildÄ«ts, kad objekts tiks savÄkts atkritumos.
PiemÄrs:
const registry = new FinalizationRegistry(heldValue => {
console.log(`Object with value ${heldValue} was garbage collected.`);
});
let obj = { data: 'some data' };
const weakRef = new WeakRef(obj);
registry.register(obj, obj.data); // Register the object with the registry
obj = null; // Remove the strong reference to the object
// At some point in the future, the garbage collector will reclaim the memory used by the object,
// and the callback in the FinalizationRegistry will be executed.
LietoŔanas gadījumi:
- KeÅ”atmiÅas pÄrvaldÄ«ba: JÅ«s varat izmantot `WeakRef`, lai ieviestu keÅ”atmiÅu, kas automÄtiski izmet ierakstus, kad attiecÄ«gie objekti vairs netiek lietoti.
- Resursu tÄ«rīŔana: JÅ«s varat izmantot `FinalizationRegistry`, lai atbrÄ«votu resursus (piemÄram, failu rokturus, tÄ«kla savienojumus), kad objekti tiek savÄkti atkritumos.
SvarÄ«gi apsvÄrumi:
- Atkritumu savÄkÅ”ana ir nedeterminÄta, tÄpÄc nevarat paļauties, ka `FinalizationRegistry` atzvani tiks izpildÄ«ti noteiktÄ laikÄ.
- Lietojiet `WeakRef` un `FinalizationRegistry` taupÄ«gi, jo tie var palielinÄt jÅ«su koda sarežģītÄ«bu.
5. IzvairīŔanÄs no globÄliem mainÄ«gajiem
GlobÄliem mainÄ«gajiem ir ilgs dzÄ«ves cikls, un tie nekad netiek savÄkti atkritumos, lÄ«dz lietojumprogramma tiek pÄrtraukta. Izvairieties no globÄlu mainÄ«go izmantoÅ”anas, lai uzglabÄtu lielus objektus vai datu struktÅ«ras, kas nepiecieÅ”amas tikai Ä«slaicÄ«gi. TÄ vietÄ izmantojiet lokÄlos mainÄ«gos funkcijÄs vai moduļos, kas tiks savÄkti atkritumos, kad tie vairs nebÅ«s tvÄrumÄ.
PiemÄrs:
Slikti:
// Global variable
let myLargeArray = new Array(1000000).fill('some data');
function processData() {
// ... use myLargeArray
}
processData();
Labi:
function processData() {
// Local variable
const myLargeArray = new Array(1000000).fill('some data');
// ... use myLargeArray
}
processData();
OtrajÄ piemÄrÄ `myLargeArray` ir lokÄls mainÄ«gais `processData` ietvaros, tÄpÄc tas tiks savÄkts atkritumos, kad `processData` beigs izpildi.
6. Resursu skaidra atbrīvoŔana
Dažos gadÄ«jumos jums var bÅ«t nepiecieÅ”ams skaidri atbrÄ«vot resursus, ko tur asinhronas operÄcijas. PiemÄram, ja izmantojat datu bÄzes savienojumu vai faila rokturi, jums tas jÄaizver, kad esat pabeidzis ar to darbu. Tas palÄ«dz novÄrst resursu noplÅ«des un uzlabo jÅ«su lietojumprogrammas vispÄrÄjo stabilitÄti.
PiemÄrs:
const fs = require('fs');
async function readFileAsync(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
async function processFile(filePath) {
let fileHandle = null;
try {
fileHandle = await fs.promises.open(filePath, 'r');
const data = await readFileAsync(filePath); // Or fileHandle.readFile()
console.log(data.toString());
} catch (error) {
console.error('Error reading file:', error);
} finally {
if (fileHandle) {
await fileHandle.close(); // Explicitly close the file handle
console.log('File handle closed.');
}
}
}
processFile('myFile.txt');
`finally` bloks nodroÅ”ina, ka faila rokturis vienmÄr tiek aizvÄrts, pat ja faila apstrÄdes laikÄ rodas kļūda.
7. Asinhrono iteratoru un ģeneratoru izmantoŔana
Asinhronie iteratori un Ä£eneratori nodroÅ”ina efektÄ«vÄku veidu, kÄ asinhroni apstrÄdÄt lielus datu apjomus. Tie ļauj apstrÄdÄt datus pa daļÄm, samazinot atmiÅas patÄriÅu un uzlabojot atsaucÄ«bu.
PiemÄrs:
async function* generateData() {
for (let i = 0; i < 100; i++) {
await new Promise(resolve => setTimeout(resolve, 10)); // Simulate asynchronous operation
yield i;
}
}
async function processData() {
for await (const item of generateData()) {
console.log(item);
}
}
processData();
Å ajÄ piemÄrÄ `generateData` funkcija ir asinhronais Ä£enerators, kas asinhroni atgriež datus. Funkcija `processData` iterÄ caur Ä£enerÄtajiem datiem, izmantojot `for await...of` ciklu. Tas ļauj apstrÄdÄt datus pa daļÄm, novÄrÅ”ot visa datu kopas ielÄdi atmiÅÄ vienlaicÄ«gi.
8. Asinhrono operÄciju ierobežoÅ”ana (Throttling) un aizturÄÅ”ana (Debouncing)
StrÄdÄjot ar biežÄm asinhronÄm operÄcijÄm, piemÄram, lietotÄja ievades apstrÄdi vai datu ielÄdi no API, ierobežoÅ”ana (throttling) un aizturÄÅ”ana (debouncing) var palÄ«dzÄt samazinÄt atmiÅas patÄriÅu un uzlabot veiktspÄju. IerobežoÅ”ana ierobežo funkcijas izpildes biežumu, savukÄrt aizturÄÅ”ana aizkavÄ funkcijas izpildi lÄ«dz noteikta laika posma beigÄm kopÅ” pÄdÄjÄ izsaukuma.
PiemÄrs (Debouncing):
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
function handleInputChange(event) {
console.log('Input changed:', event.target.value);
// Perform asynchronous operation here (e.g., search API call)
}
const debouncedHandleInputChange = debounce(handleInputChange, 300); // Debounce for 300ms
const inputElement = document.getElementById('myInput');
inputElement.addEventListener('input', debouncedHandleInputChange);
Å ajÄ piemÄrÄ `debounce` funkcija ietin `handleInputChange` funkciju. AizturÄtÄ funkcija tiks izpildÄ«ta tikai pÄc 300 milisekunžu neaktivitÄtes. Tas novÄrÅ” pÄrmÄrÄ«gus API izsaukumus un samazina atmiÅas patÄriÅu.
9. Apsveriet bibliotÄkas vai ietvara izmantoÅ”anu
Daudzas JavaScript bibliotÄkas un ietvari nodroÅ”ina iebÅ«vÄtus mehÄnismus asinhrono operÄciju pÄrvaldÄ«bai un atmiÅas noplūžu novÄrÅ”anai. PiemÄram, React `useEffect` ÄÄ·is ļauj viegli pÄrvaldÄ«t blakusefektus un tos notÄ«rÄ«t, kad komponenti tiek noÅemti (unmount). LÄ«dzÄ«gi, Angular RxJS bibliotÄka nodroÅ”ina jaudÄ«gu operatoru kopu asinhrono datu plÅ«smu apstrÄdei un abonementu (subscriptions) pÄrvaldÄ«bai.
PiemÄrs (React useEffect):
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [data, setData] = useState(null);
useEffect(() => {
let isMounted = true; // Track component mount state
async function fetchData() {
const response = await fetch('https://example.com/api/data');
const result = await response.json();
if (isMounted) {
setData(result);
}
}
fetchData();
return () => {
// Cleanup function
isMounted = false; // Prevent state updates on unmounted component
// Cancel any pending asynchronous operations here
};
}, []); // Empty dependency array means this effect runs only once on mount
return (
{data ? Data: {data.value}
: Loading...
}
);
}
export default MyComponent;
`useEffect` ÄÄ·is nodroÅ”ina, ka komponents atjaunina savu stÄvokli tikai tad, ja tas joprojÄm ir pievienots (mounted). TÄ«rīŔanas funkcija iestata `isMounted` uz `false`, novÄrÅ”ot jebkÄdas turpmÄkas stÄvokļa atjauninÄÅ”anas pÄc komponenta noÅemÅ”anas. Tas novÄrÅ” atmiÅas noplÅ«des, kas var rasties, kad asinhronÄs operÄcijas pabeidzas pÄc komponenta iznÄ«cinÄÅ”anas.
NoslÄgums
EfektÄ«va atmiÅas pÄrvaldÄ«ba ir izŔķiroÅ”a, lai veidotu robustas un mÄrogojamas JavaScript lietojumprogrammas, Ä«paÅ”i strÄdÄjot ar asinhronÄm operÄcijÄm. Izprotot asinhronÄ konteksta sarežģītÄ«bu, identificÄjot potenciÄlÄs atmiÅas noplÅ«des un ievieÅ”ot Å”ajÄ rakstÄ aprakstÄ«tÄs optimizÄcijas metodes, jÅ«s varat bÅ«tiski uzlabot savu lietojumprogrammu veiktspÄju un uzticamÄ«bu. Atcerieties izmantot profilÄÅ”anas rÄ«kus, veikt rÅ«pÄ«gas koda pÄrskates un izmantot mÅ«sdienu JavaScript funkciju, piemÄram, `WeakRef` un `FinalizationRegistry`, spÄku, lai nodroÅ”inÄtu, ka jÅ«su lietojumprogrammas ir atmiÅas efektÄ«vas un veiktspÄjÄ«gas.