ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഉപയോഗിച്ച് JavaScript റിസോഴ്സ് മാനേജ്മെന്റ് ഒപ്റ്റിമൈസ് ചെയ്യുക. ആധുനിക JavaScript ഫീച്ചറുകൾ ഉപയോഗിച്ച് ശക്തവും കാര്യക്ഷമവുമായ സ്ട്രീം റിസോഴ്സ് സിസ്റ്റം നിർമ്മിക്കുക.
JavaScript ഇറ്ററേറ്റർ ഹെൽപ്പർ റിസോഴ്സ് മാനേജർ: സ്ട്രീം റിസോഴ്സ് സിസ്റ്റം
ആധുനിക JavaScript ഡാറ്റാ സ്ട്രീമുകളും റിസോഴ്സുകളും കാര്യക്ഷമമായി കൈകാര്യം ചെയ്യാൻ ശക്തമായ ടൂളുകൾ നൽകുന്നു. Async ഇറ്ററേറ്ററുകൾ, ജനറേറ്റർ ഫംഗ്ഷനുകൾ തുടങ്ങിയ ഫീച്ചറുകളുമായി സംയോജിപ്പിച്ച്, ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഡെവലപ്പർമാരെ ശക്തവും സ്കെയിലബിളുമായിട്ടുള്ള സ്ട്രീം റിസോഴ്സ് സിസ്റ്റങ്ങൾ നിർമ്മിക്കാൻ അനുവദിക്കുന്നു. കാര്യക്ഷമമായി റിസോഴ്സുകൾ കൈകാര്യം ചെയ്യുകയും പ്രകടനം ഒപ്റ്റിമൈസ് ചെയ്യുകയും കോഡ് റീഡബിലിറ്റി മെച്ചപ്പെടുത്തുകയും ചെയ്യുന്ന ഒരു സിസ്റ്റം എങ്ങനെ നിർമ്മിക്കാമെന്ന് ഈ ലേഖനം പരിശോധിക്കുന്നു.
JavaScript-ൽ റിസോഴ്സ് മാനേജ്മെൻ്റിൻ്റെ ആവശ്യം മനസ്സിലാക്കുക
JavaScript ആപ്ലിക്കേഷനുകളിൽ, പ്രത്യേകിച്ചും വലിയ ഡാറ്റാ സെറ്റുകളോ ബാഹ്യ API-കളോ കൈകാര്യം ചെയ്യുന്നവയിൽ, കാര്യക്ഷമമായ റിസോഴ്സ് മാനേജ്മെൻ്റ് നിർണായകമാണ്. കൈകാര്യം ചെയ്യപ്പെടാത്ത റിസോഴ്സുകൾ പ്രകടന പ്രശ്നങ്ങളിലേക്കും മെമ്മറി ചോർച്ചയിലേക്കും മോശം ഉപയോക്തൃ അനുഭവത്തിലേക്കും നയിച്ചേക്കാം. റിസോഴ്സ് മാനേജ്മെൻ്റ് നിർണായകമായ ചില സാധാരണ സാഹചര്യങ്ങൾ ഇതാ:
- വലിയ ഫയലുകൾ പ്രോസസ്സ് ചെയ്യുക: വലിയ ഫയലുകൾ വായിക്കുന്നതും പ്രോസസ്സ് ചെയ്യുന്നതും, പ്രത്യേകിച്ചും ഒരു ബ്രൗസർ പരിതസ്ഥിതിയിൽ, മെയിൻ ത്രെഡിനെ തടസ്സപ്പെടുത്താതിരിക്കാൻ ശ്രദ്ധാപൂർവ്വമായ മാനേജ്മെൻ്റ് ആവശ്യമാണ്.
- API-കളിൽ നിന്ന് ഡാറ്റ സ്ട്രീം ചെയ്യുക: വലിയ ഡാറ്റാ സെറ്റുകൾ നൽകുന്ന API-കളിൽ നിന്ന് ഡാറ്റ എടുക്കുന്നത്, ക്ലയിൻ്റിനെ ബുദ്ധിമുട്ടിക്കാതിരിക്കാൻ സ്ട്രീമിംഗ് രീതിയിൽ കൈകാര്യം ചെയ്യണം.
- ഡാറ്റാബേസ് കണക്ഷനുകൾ മാനേജ് ചെയ്യുക: ആപ്ലിക്കേഷൻ്റെ പ്രതികരണശേഷിയും സ്കെയിലബിലിറ്റിയും ഉറപ്പാക്കാൻ ഡാറ്റാബേസ് കണക്ഷനുകൾ കാര്യക്ഷമമായി കൈകാര്യം ചെയ്യേണ്ടത് അത്യാവശ്യമാണ്.
- ഇവന്റ്-ഡ്രിവൺ സിസ്റ്റങ്ങൾ: ഇവന്റ് സ്ട്രീമുകൾ കൈകാര്യം ചെയ്യുന്നതും ഇവന്റ് ലിസണർമാർ ശരിയായി ക്ലീൻ അപ്പ് ചെയ്യപ്പെടുന്നുണ്ടെന്ന് ഉറപ്പാക്കുന്നതും മെമ്മറി ചോർച്ച തടയുന്നതിന് അത്യാവശ്യമാണ്.
ഒരു നല്ല രൂപകൽപ്പന ചെയ്ത റിസോഴ്സ് മാനേജ്മെൻ്റ് സിസ്റ്റം, ആവശ്യമുള്ളപ്പോൾ റിസോഴ്സുകൾ നേടുകയും കാര്യക്ഷമമായി ഉപയോഗിക്കുകയും ആവശ്യമില്ലാത്തപ്പോൾ ഉടൻ തന്നെ റിലീസ് ചെയ്യുകയും ചെയ്യുന്നു. ഇത് ആപ്ലിക്കേഷൻ്റെ ഫൂട്ട്പ്രിൻ്റ് കുറയ്ക്കുകയും പ്രകടനം മെച്ചപ്പെടുത്തുകയും സ്ഥിരത വർദ്ധിപ്പിക്കുകയും ചെയ്യുന്നു.
ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സിനെ പരിചയപ്പെടുത്തുന്നു
ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ്, Array.prototype.values() രീതികൾ എന്നും അറിയപ്പെടുന്നു, ഇത് ഇറ്ററേബിൾ ഡാറ്റാ ഘടനകളുമായി പ്രവർത്തിക്കാൻ ശക്തമായ മാർഗ്ഗം നൽകുന്നു. ഈ രീതികൾ ഇറ്ററേറ്ററുകളിൽ പ്രവർത്തിക്കുന്നു, ഇത് ഡാറ്റയെ ഡിക്ലറേറ്റീവ് ആയും കാര്യക്ഷമമായും മാറ്റാനും ഫിൽട്ടർ ചെയ്യാനും ഉപയോഗിക്കാനും നിങ്ങളെ അനുവദിക്കുന്നു. നിലവിൽ ഇത് സ്റ്റേജ് 4 പ്രൊപ്പോസൽ ആണെങ്കിലും എല്ലാ ബ്രൗസറുകളിലും നേറ്റീവ് ആയി പിന്തുണക്കുന്നില്ല, Babel പോലുള്ള ട്രാൻസ്പൈലറുകൾ ഉപയോഗിച്ച് പോളിഫിൽ ചെയ്യാനോ ഉപയോഗിക്കാനോ കഴിയും. സാധാരണയായി ഉപയോഗിക്കുന്ന ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സിൽ ഇവ ഉൾപ്പെടുന്നു:
map(): ഇറ്ററേറ്ററിലെ ഓരോ എലമെൻ്റിനെയും രൂപാന്തരപ്പെടുത്തുന്നു.filter(): നൽകിയിട്ടുള്ള പ്രെഡിക്കേറ്റിനെ അടിസ്ഥാനമാക്കി എലമെൻ്റുകളെ ഫിൽട്ടർ ചെയ്യുന്നു.take(): ആദ്യത്തെ n എലമെൻ്റുകളുള്ള ഒരു പുതിയ ഇറ്ററേറ്റർ നൽകുന്നു.drop(): ആദ്യത്തെ n എലമെൻ്റുകൾ ഒഴിവാക്കുന്ന ഒരു പുതിയ ഇറ്ററേറ്റർ നൽകുന്നു.reduce(): ഇറ്ററേറ്ററിലെ മൂല്യങ്ങളെ ഒരു സിംഗിൾ റിസൾട്ടിലേക്ക് അക്യുമുലേറ്റ് ചെയ്യുന്നു.forEach(): ഓരോ എലമെൻ്റിനും വേണ്ടി നൽകിയിട്ടുള്ള ഫംഗ്ഷൻ ഒരു തവണ എക്സിക്യൂട്ട് ചെയ്യുന്നു.
അസിൻക്രണസ് ഡാറ്റാ സ്ട്രീമുകളുമായി പ്രവർത്തിക്കാൻ ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് പ്രത്യേകിച്ചും ഉപയോഗപ്രദമാണ്, കാരണം അവ ഡാറ്റയെ ലേസിയായി പ്രോസസ്സ് ചെയ്യാൻ നിങ്ങളെ അനുവദിക്കുന്നു. ഇതിനർത്ഥം ഡാറ്റ ആവശ്യമുള്ളപ്പോൾ മാത്രമേ പ്രോസസ്സ് ചെയ്യൂ, ഇത് വലിയ ഡാറ്റാ സെറ്റുകൾ കൈകാര്യം ചെയ്യുമ്പോൾ പ്രകടനം ഗണ്യമായി മെച്ചപ്പെടുത്തും.
ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഉപയോഗിച്ച് ഒരു സ്ട്രീം റിസോഴ്സ് സിസ്റ്റം നിർമ്മിക്കുന്നു
ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഉപയോഗിച്ച് ഒരു സ്ട്രീം റിസോഴ്സ് സിസ്റ്റം എങ്ങനെ നിർമ്മിക്കാമെന്ന് നമുക്ക് നോക്കാം. ഫയൽ സ്ട്രീമിൽ നിന്ന് ഡാറ്റ റീഡ് ചെയ്യുന്നതിൻ്റെയും ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഉപയോഗിച്ച് അത് പ്രോസസ്സ് ചെയ്യുന്നതിൻ്റെയും അടിസ്ഥാന ഉദാഹരണത്തിൽ നിന്ന് നമുക്ക് ആരംഭിക്കാം.
ഉദാഹരണം: ഒരു ഫയൽ സ്ട്രീം റീഡ് ചെയ്ത് പ്രോസസ്സ് ചെയ്യുന്നു
നിങ്ങൾ ഒരു വലിയ ഫയൽ റീഡ് ചെയ്യുകയും ഓരോ ലൈനും പ്രോസസ്സ് ചെയ്യുകയും പ്രത്യേക വിവരങ്ങൾ എക്സ്ട്രാക്റ്റ് ചെയ്യുകയും ചെയ്യേണ്ട ഒരു സാഹചര്യം പരിഗണിക്കുക. പരമ്പരാഗത രീതികൾ ഉപയോഗിച്ച്, നിങ്ങൾ ഫയൽ മുഴുവൻ മെമ്മറിയിലേക്ക് ലോഡ് ചെയ്തേക്കാം, ഇത് കാര്യക്ഷമമല്ലാത്ത ഒന്നാണ്. ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സും അസിൻക്രണസ് ഇറ്ററേറ്ററുകളും ഉപയോഗിച്ച്, നിങ്ങൾക്ക് ഫയൽ സ്ട്രീം ലൈൻ ബൈ ലൈൻ ആയി പ്രോസസ്സ് ചെയ്യാൻ കഴിയും.
ആദ്യം, ഫയൽ സ്ട്രീം ലൈൻ ബൈ ലൈൻ ആയി റീഡ് ചെയ്യുന്ന ഒരു അസിൻക്രണസ് ജനറേറ്റർ ഫംഗ്ഷൻ നമുക്ക് നിർമ്മിക്കാം:
async function* readFileLines(filePath) {
const fileStream = fs.createReadStream(filePath, { encoding: 'utf8' });
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
try {
for await (const line of rl) {
yield line;
}
} finally {
// Ensure the file stream is closed, even if errors occur
fileStream.destroy();
}
}
ഈ ഫംഗ്ഷൻ Node.js-ൻ്റെ fs, readline മൊഡ്യൂളുകൾ ഉപയോഗിച്ച് ഒരു റീഡ് സ്ട്രീം നിർമ്മിക്കുകയും ഫയലിലെ ഓരോ ലൈനിലൂടെയും ഇറ്ററേറ്റ് ചെയ്യുകയും ചെയ്യുന്നു. finally ബ്ലോക്ക്, റീഡിംഗ് പ്രക്രിയയിൽ ഒരു പിശക് സംഭവിച്ചാലും ഫയൽ സ്ട്രീം ശരിയായി ക്ലോസ് ചെയ്യുന്നുവെന്ന് ഉറപ്പാക്കുന്നു. ഇത് റിസോഴ്സ് മാനേജ്മെൻ്റിൻ്റെ ഒരു നിർണായക ഭാഗമാണ്.
അടുത്തതായി, ഫയൽ സ്ട്രീമിൽ നിന്നുള്ള ലൈനുകൾ പ്രോസസ്സ് ചെയ്യാൻ ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഉപയോഗിക്കാം:
async function processFile(filePath) {
const lines = readFileLines(filePath);
// Simulate Iterator Helpers
async function* map(iterable, transform) {
for await (const item of iterable) {
yield transform(item);
}
}
async function* filter(iterable, predicate) {
for await (const item of iterable) {
if (predicate(item)) {
yield item;
}
}
}
// Using "Iterator Helpers" (simulated here)
const processedLines = map(filter(lines, line => line.length > 0), line => line.toUpperCase());
for await (const line of processedLines) {
console.log(line);
}
}
ഈ ഉദാഹരണത്തിൽ, ഞങ്ങൾ ആദ്യം ശൂന്യമായ ലൈനുകൾ ഫിൽട്ടർ ചെയ്യുന്നു, തുടർന്ന് ബാക്കിയുള്ള ലൈനുകളെ വലിയക്ഷരത്തിലേക്ക് മാറ്റുന്നു. ഈ സിമുലേറ്റഡ് ഇറ്ററേറ്റർ ഹെൽപ്പർ ഫംഗ്ഷനുകൾ സ്ട്രീമിനെ എങ്ങനെ ലേസിയായി പ്രോസസ്സ് ചെയ്യാമെന്ന് കാണിക്കുന്നു. for await...of ലൂപ്പ് പ്രോസസ്സ് ചെയ്ത ലൈനുകൾ ഉപയോഗിക്കുകയും അവയെ കൺസോളിലേക്ക് ലോഗ് ചെയ്യുകയും ചെയ്യുന്നു.
ഈ സമീപനത്തിൻ്റെ പ്രയോജനങ്ങൾ
- മെമ്മറി കാര്യക്ഷമത: ഫയൽ ലൈൻ ബൈ ലൈൻ ആയി പ്രോസസ്സ് ചെയ്യുന്നു, ഇത് ആവശ്യമായ മെമ്മറിയുടെ അളവ് കുറയ്ക്കുന്നു.
- മെച്ചപ്പെട്ട പ്രകടനം: ലേസി ഇവാലുവേഷൻ ആവശ്യമുള്ള ഡാറ്റ മാത്രമേ പ്രോസസ്സ് ചെയ്യുന്നുള്ളൂ എന്ന് ഉറപ്പാക്കുന്നു.
- റിസോഴ്സ് സുരക്ഷ:
finallyബ്ലോക്ക്, ഒരു പിശക് സംഭവിച്ചാലും ഫയൽ സ്ട്രീം ശരിയായി അടച്ചിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുന്നു. - വായിക്കാൻ എളുപ്പം: സങ്കീർണ്ണമായ ഡാറ്റാ ട്രാൻസ്ഫോർമേഷനുകൾ പ്രകടിപ്പിക്കാൻ ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഒരു ഡിക്ലറേറ്റീവ് മാർഗ്ഗം നൽകുന്നു.
വിപുലമായ റിസോഴ്സ് മാനേജ്മെൻ്റ് ടെക്നിക്കുകൾ
അടിസ്ഥാന ഫയൽ പ്രോസസ്സിംഗിനപ്പുറം, കൂടുതൽ വിപുലമായ റിസോഴ്സ് മാനേജ്മെൻ്റ് ടെക്നിക്കുകൾ നടപ്പിലാക്കാൻ ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഉപയോഗിക്കാം. ചില ഉദാഹരണങ്ങൾ ഇതാ:
1. റേറ്റ് ലിമിറ്റിംഗ്
ബാഹ്യ API-കളുമായി സംവദിക്കുമ്പോൾ, API ഉപയോഗ പരിധികൾ കവിയുന്നത് ഒഴിവാക്കാൻ റേറ്റ് ലിമിറ്റിംഗ് നടപ്പിലാക്കേണ്ടത് പലപ്പോഴും ആവശ്യമാണ്. API-ലേക്ക് അഭ്യർത്ഥനകൾ അയയ്ക്കുന്ന നിരക്ക് നിയന്ത്രിക്കാൻ ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഉപയോഗിക്കാം.
async function* rateLimit(iterable, delay) {
for await (const item of iterable) {
yield item;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
async function* fetchFromAPI(urls) {
for (const url of urls) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
yield await response.json();
}
}
async function processAPIResponses(urls, rateLimitDelay) {
const apiResponses = fetchFromAPI(urls);
const rateLimitedResponses = rateLimit(apiResponses, rateLimitDelay);
for await (const response of rateLimitedResponses) {
console.log(response);
}
}
// Example usage:
const apiUrls = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3'
];
// Set a rate limit of 500ms between requests
await processAPIResponses(apiUrls, 500);
ഈ ഉദാഹരണത്തിൽ, rateLimit ഫംഗ്ഷൻ, ഇറ്ററേബിളിൽ നിന്ന് പുറപ്പെടുവിക്കുന്ന ഓരോ ഇനത്തിനും ഇടയിൽ ഒരു കാലതാമസം അവതരിപ്പിക്കുന്നു. ഇത് API അഭ്യർത്ഥനകൾ നിയന്ത്രിത നിരക്കിലാണ് അയയ്ക്കുന്നതെന്ന് ഉറപ്പാക്കുന്നു. fetchFromAPI ഫംഗ്ഷൻ നിർദ്ദിഷ്ട URL-കളിൽ നിന്ന് ഡാറ്റ എടുക്കുകയും JSON പ്രതികരണങ്ങൾ നൽകുകയും ചെയ്യുന്നു. processAPIResponses ഈ ഫംഗ്ഷനുകളെ സംയോജിപ്പിച്ച് റേറ്റ് ലിമിറ്റിംഗോടെ API പ്രതികരണങ്ങൾ എടുക്കുകയും പ്രോസസ്സ് ചെയ്യുകയും ചെയ്യുന്നു. ശരിയായ പിശക് കൈകാര്യം ചെയ്യലും (ഉദാഹരണത്തിന്, response.ok പരിശോധിക്കുന്നത്) ഇതിൽ ഉൾപ്പെടുന്നു.
2. റിസോഴ്സ് പൂളിംഗ്
റിസോഴ്സ് പൂളിംഗിൽ, റിസോഴ്സുകൾ വീണ്ടും വീണ്ടും നിർമ്മിക്കുന്നതിൻ്റെയും നശിപ്പിക്കുന്നതിൻ്റെയും ഓവർഹെഡ് ഒഴിവാക്കാൻ വീണ്ടും ഉപയോഗിക്കാവുന്ന റിസോഴ്സുകളുടെ ഒരു പൂൾ നിർമ്മിക്കുന്നത് ഉൾപ്പെടുന്നു. പൂളിൽ നിന്ന് റിസോഴ്സുകൾ നേടുന്നതും റിലീസ് ചെയ്യുന്നതും കൈകാര്യം ചെയ്യാൻ ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഉപയോഗിക്കാം.
ഡാറ്റാബേസ് കണക്ഷനുകൾക്കായുള്ള ലളിതമായ ഒരു റിസോഴ്സ് പൂൾ ഈ ഉദാഹരണം കാണിക്കുന്നു:
class ConnectionPool {
constructor(size, createConnection) {
this.size = size;
this.createConnection = createConnection;
this.pool = [];
this.available = [];
this.initializePool();
}
async initializePool() {
for (let i = 0; i < this.size; i++) {
const connection = await this.createConnection();
this.pool.push(connection);
this.available.push(connection);
}
}
async acquire() {
if (this.available.length > 0) {
return this.available.pop();
}
// Optionally handle the case where no connections are available, e.g., wait or throw an error.
throw new Error("No available connections in the pool.");
}
release(connection) {
this.available.push(connection);
}
async useConnection(callback) {
const connection = await this.acquire();
try {
return await callback(connection);
} finally {
this.release(connection);
}
}
}
// Example Usage (assuming you have a function to create a database connection)
async function createDBConnection() {
// Simulate creating a database connection
return new Promise(resolve => {
setTimeout(() => {
resolve({ id: Math.random(), query: (sql) => Promise.resolve(`Executed: ${sql}`) }); // Simulate a connection object
}, 100);
});
}
async function main() {
const poolSize = 5;
const pool = new ConnectionPool(poolSize, createDBConnection);
// Wait for the pool to initialize
await new Promise(resolve => setTimeout(resolve, 100 * poolSize));
// Use the connection pool to execute queries
for (let i = 0; i < 10; i++) {
try {
const result = await pool.useConnection(async (connection) => {
return await connection.query(`SELECT * FROM users WHERE id = ${i}`);
});
console.log(`Query ${i} Result: ${result}`);
} catch (error) {
console.error(`Error executing query ${i}: ${error.message}`);
}
}
}
main();
ഈ ഉദാഹരണം ഡാറ്റാബേസ് കണക്ഷനുകളുടെ ഒരു പൂൾ കൈകാര്യം ചെയ്യുന്ന ConnectionPool ക്ലാസ് നിർവചിക്കുന്നു. acquire രീതി പൂളിൽ നിന്ന് ഒരു കണക്ഷൻ എടുക്കുന്നു, കൂടാതെ release രീതി കണക്ഷനെ പൂളിലേക്ക് തിരികെ നൽകുന്നു. useConnection രീതി ഒരു കണക്ഷൻ നേടുകയും കണക്ഷൻ ഉപയോഗിച്ച് ഒരു കോൾബാക്ക് ഫംഗ്ഷൻ എക്സിക്യൂട്ട് ചെയ്യുകയും തുടർന്ന് കണക്ഷനുകൾ എല്ലായ്പ്പോഴും പൂളിലേക്ക് തിരികെ നൽകുന്നുവെന്ന് ഉറപ്പാക്കുകയും ചെയ്യുന്നു. ഈ സമീപനം ഡാറ്റാബേസ് ഉറവിടങ്ങളുടെ കാര്യക്ഷമമായ ഉപയോഗത്തെ പ്രോത്സാഹിപ്പിക്കുകയും പുതിയ കണക്ഷനുകൾ ആവർത്തിച്ച് നിർമ്മിക്കുന്നതിൻ്റെ ഓവർഹെഡ് ഒഴിവാക്കുകയും ചെയ്യുന്നു.
3. ത്രോട്ടിലിംഗ്
ത്രോട്ടിലിംഗ് ഒരു സിസ്റ്റത്തെ അമിതമായി ബുദ്ധിമുട്ടിക്കുന്നത് തടയാൻ ഒരേസമയം നടക്കുന്ന പ്രവർത്തനങ്ങളുടെ എണ്ണം പരിമിതപ്പെടുത്തുന്നു. അസിൻക്രണസ് ടാസ്ക്കുകളുടെ എക്സിക്യൂഷൻ ത്രോട്ടിൽ ചെയ്യാൻ ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് ഉപയോഗിക്കാം.
async function* throttle(iterable, concurrency) {
const queue = [];
let running = 0;
let iterator = iterable[Symbol.asyncIterator]();
async function execute() {
if (queue.length === 0 || running >= concurrency) {
return;
}
running++;
const { value, done } = queue.shift();
try {
yield await value;
} finally {
running--;
if (!done) {
execute(); // Continue processing if not done
}
}
if (queue.length > 0) {
execute(); // Start another task if available
}
}
async function fillQueue() {
while (running < concurrency) {
const { value, done } = await iterator.next();
if (done) {
return;
}
queue.push({ value, done });
execute();
}
}
await fillQueue();
}
async function* generateTasks(count) {
for (let i = 1; i <= count; i++) {
yield new Promise(resolve => {
const delay = Math.random() * 1000;
setTimeout(() => {
console.log(`Task ${i} completed after ${delay}ms`);
resolve(`Result from task ${i}`);
}, delay);
});
}
}
async function main() {
const taskCount = 10;
const concurrencyLimit = 3;
const tasks = generateTasks(taskCount);
const throttledTasks = throttle(tasks, concurrencyLimit);
for await (const result of throttledTasks) {
console.log(`Received: ${result}`);
}
console.log('All tasks completed');
}
main();
ഈ ഉദാഹരണത്തിൽ, throttle ഫംഗ്ഷൻ ഒരേസമയം നടക്കുന്ന അസിൻക്രണസ് ടാസ്ക്കുകളുടെ എണ്ണം പരിമിതപ്പെടുത്തുന്നു. ഇത് തീർപ്പാക്കാത്ത ടാസ്ക്കുകളുടെ ഒരു ക്യൂ പരിപാലിക്കുകയും നിർദ്ദിഷ്ട കൺകറൻസി പരിധി വരെ അവ എക്സിക്യൂട്ട് ചെയ്യുകയും ചെയ്യുന്നു. generateTasks ഫംഗ്ഷൻ ക്രമരഹിതമായ കാലതാമസത്തിന് ശേഷം പരിഹരിക്കുന്ന അസിൻക്രണസ് ടാസ്ക്കുകളുടെ ഒരു കൂട്ടം സൃഷ്ടിക്കുന്നു. main ഫംഗ്ഷൻ ഈ ഫംഗ്ഷനുകളെ സംയോജിപ്പിച്ച് ത്രോട്ടിലിംഗോടെ ടാസ്ക്കുകൾ എക്സിക്യൂട്ട് ചെയ്യുന്നു. ഇത് നിരവധി പ്രവർത്തനങ്ങൾ ഒരേസമയം നടക്കുന്നത് കാരണം സിസ്റ്റം അമിതമായി ബുദ്ധിമുട്ടുന്നില്ലെന്ന് ഉറപ്പാക്കുന്നു.
പിശക് കൈകാര്യം ചെയ്യൽ
ശക്തമായ പിശക് കൈകാര്യം ചെയ്യൽ ഏതൊരു റിസോഴ്സ് മാനേജ്മെൻ്റ് സിസ്റ്റത്തിൻ്റെയും ഒരു പ്രധാന ഭാഗമാണ്. അസിൻക്രണസ് ഡാറ്റാ സ്ട്രീമുകളുമായി പ്രവർത്തിക്കുമ്പോൾ, റിസോഴ്സ് ചോർച്ച തടയുന്നതിനും ആപ്ലിക്കേഷൻ്റെ സ്ഥിരത ഉറപ്പാക്കുന്നതിനും പിശകുകൾ ഭംഗിയായി കൈകാര്യം ചെയ്യേണ്ടത് പ്രധാനമാണ്. ഒരു പിശക് സംഭവിച്ചാലും ഉറവിടങ്ങൾ ശരിയായി വൃത്തിയാക്കുന്നുവെന്ന് ഉറപ്പാക്കാൻ try-catch-finally ബ്ലോക്കുകൾ ഉപയോഗിക്കുക.
ഉദാഹരണത്തിന്, മുകളിലുള്ള readFileLines ഫംഗ്ഷനിൽ, റീഡിംഗ് പ്രക്രിയയിൽ ഒരു പിശക് സംഭവിച്ചാലും finally ബ്ലോക്ക് ഫയൽ സ്ട്രീം അടച്ചിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുന്നു.
ഉപസംഹാരം
JavaScript ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് അസിൻക്രണസ് ഡാറ്റാ സ്ട്രീമുകളിൽ റിസോഴ്സുകൾ കൈകാര്യം ചെയ്യാൻ ശക്തവും കാര്യക്ഷമവുമായ മാർഗ്ഗം നൽകുന്നു. Async ഇറ്ററേറ്ററുകൾ, ജനറേറ്റർ ഫംഗ്ഷനുകൾ തുടങ്ങിയ ഫീച്ചറുകളുമായി ഇറ്ററേറ്റർ ഹെൽപ്പേഴ്സ് സംയോജിപ്പിച്ച്, ഡെവലപ്പർമാർക്ക് ശക്തവും സ്കെയിലബിളും പരിപാലിക്കാൻ എളുപ്പമുള്ളതുമായ സ്ട്രീം റിസോഴ്സ് സിസ്റ്റങ്ങൾ നിർമ്മിക്കാൻ കഴിയും. JavaScript ആപ്ലിക്കേഷനുകളുടെ പ്രകടനം, സ്ഥിരത, വിശ്വാസ്യത എന്നിവ ഉറപ്പാക്കുന്നതിന് ശരിയായ റിസോഴ്സ് മാനേജ്മെൻ്റ് നിർണായകമാണ്, പ്രത്യേകിച്ചും വലിയ ഡാറ്റാ സെറ്റുകളോ ബാഹ്യ API-കളോ കൈകാര്യം ചെയ്യുന്നവയിൽ. റേറ്റ് ലിമിറ്റിംഗ്, റിസോഴ്സ് പൂളിംഗ്, ത്രോട്ടിലിംഗ് തുടങ്ങിയ ടെക്നിക്കുകൾ നടപ്പിലാക്കുന്നതിലൂടെ, നിങ്ങൾക്ക് റിസോഴ്സ് ഉപയോഗം ഒപ്റ്റിമൈസ് ചെയ്യാനും തടസ്സങ്ങൾ തടയാനും മൊത്തത്തിലുള്ള ഉപയോക്തൃ അനുഭവം മെച്ചപ്പെടുത്താനും കഴിയും.