TypeScript using కీవర్డ్ మరియు Explicit Resource Management

ప్రొడక్షన్‌లో మెమరీ లీక్‌లు (Memory leaks) తరచుగా ఒకే ఒక తప్పు వల్ల జరుగుతాయి: డెవలపర్లు వనరులను (resources) పొందుతారు కానీ వాటిని విడుదల చేయడంలో విఫలమవుతారు.

ఎర్రర్స్ వచ్చిన తర్వాత కూడా డేటాబేస్ కనెక్షన్‌లు తెరిచే ఉంటాయి. ఫైల్ హ్యాండిల్స్ (File handles) సిస్టమ్ వనరులను వినియోగిస్తాయి. WebSocket క్లయింట్లు పని చేయని సర్వర్‌లకు కనెక్ట్ అయి ఉంటాయి. మీరు finally బ్లాక్‌లలో మాన్యువల్ క్లీనప్ (manual cleanup) పై ఆధారపడినప్పుడు ఇలా జరుగుతుంది.

TypeScript using కీవర్డ్ దీనిని పరిష్కరిస్తుంది. ఇది ECMAScript Explicit Resource Management ప్రతిపాదనలో భాగం. ఇది disposable pattern ద్వారా క్లీనప్‌ను గ్యారెంటీ చేస్తుంది. ఒక వనరు దాని స్కోప్ (scope) నుండి బయటకు వచ్చినప్పుడు, TypeScript దాని disposal మెథడ్‌ను ఆటోమేటిక్‌గా రన్ చేస్తుంది.

ఇకపై మీకు మాన్యువల్ finally బ్లాక్‌లు అవసరం లేదు. మీరు క్లీనప్‌ను మర్చిపోరు. కనెక్షన్‌లు లీక్ అవ్వవు.

ఇది ఎలా పనిచేస్తుంది:

  • using కీవర్డ్ వనరులు స్కోప్ నుండి బయటకు వచ్చినప్పుడు వాటిని డిస్పోజ్ (disposal) చేయడాన్ని నిర్ధారిస్తుంది.
  • Disposable వనరులు సింక్రోనస్ (sync) పనుల కోసం Symbol.disposeని లేదా అసింక్రోనస్ (async) పనుల కోసం Symbol.asyncDisposeని ఇంప్లిమెంట్ చేస్తాయి.
  • TypeScript using డిక్లరేషన్‌లను ఆటోమేటిక్ డిస్పోజల్ స్టాక్‌తో కూడిన try-finally బ్లాక్‌లుగా మారుస్తుంది.
  • ఈ ప్యాటర్న్ త్వరగా రిటర్న్ అవ్వడం (early returns), ఎర్రర్స్ రావడం (thrown exceptions) లేదా కోడ్ మర్చిపోవడం వల్ల కలిగే లీక్‌లను నివారిస్తుంది.

డేటాబేస్ కనెక్షన్‌లు, ఫైల్ హ్యాండిల్స్, లాక్స్ (locks) లేదా టైమర్‌ల వంటి నిర్ణీత కాలపరిమితి కలిగిన ఏ వనరుకైనా usingని ఉపయోగించండి.

ఈ మెకానిజం ఒక disposal ప్రోటోకాల్‌ను ఉపయోగిస్తుంది. ఆబ్జెక్ట్‌లు Symbol.dispose ద్వారా కీ చేయబడిన మెథడ్‌ను ఇంప్లిమెంట్ చేస్తాయి. స్కోప్ సాధారణంగా పూర్తయినప్పుడు, రిటర్న్ అయినప్పుడు లేదా ఎర్రర్ వచ్చినప్పుడు, TypeScript ఆ మెథడ్‌ను పిలుస్తుంది.

ఫైల్ హ్యాండిల్ ఉదాహరణ:

class FileHandle {
  private handle: number;

  constructor(path: string) {
    this.handle = openFileSync(path);
  }

  [Symbol.dispose]() {
    if (this.handle !== -1) {
      closeFileSync(this.handle);
      this.handle = -1;
    }
  }

  read(buffer: Buffer): number {
    return readSync(this.handle, buffer);
  }
}

function processFile(path: string) {
  using file = new FileHandle(path);
  const buffer = Buffer.alloc(1024);
  file.read(buffer);
}

డిస్పోజల్ అనేది జనరేట్ చేయబడిన finally బ్లాక్‌లో రన్ అవుతుంది. ఫంక్షన్ ఎర్రర్‌ను త్రో చేసినా లేదా త్వరగా రిటర్న్ అయినా ఇది రన్ అవుతుంది.

TypeScript ఒక disposal స్టాక్‌ను నిర్వహిస్తుంది. మీరు వనరులను పొందిన క్రమానికి వ్యతిరేక క్రమంలో (reverse order) ఇది వాటిని డిస్పోజ్ చేస్తుంది. ఇది చాలా క్లీనప్ లాజిక్‌లకు సహజమైన డిపెండెన్సీ ఆర్డర్‌తో సరిపోలుతుంది.

అసింక్రోనస్ క్లీనప్ కోసం, await usingని ఉపయోగించండి. దీని కోసం వనరు Symbol.asyncDisposeని ఇంప్లిమెంట్ చేయాల్సి ఉంటుంది. TypeScript తదుపరి దశకు వెళ్లే ముందు రిటర్న్ అయిన Promise కోసం వేచి ఉంటుంది (await చేస్తుంది).

విజయవంతంగా ఉపయోగించడానికి మూడు నియమాలు:

  • మీ disposal మెథడ్‌ల లోపల ఎక్సెప్షన్స్‌ను (exceptions) త్రో చేయవద్దు. దానికి బదులుగా ఎర్రర్‌లను క్యాచీ (catch) చేసి అంతర్గతంగా లాగ్ చేయండి.
  • సింక్రోనస్ Symbol.dispose మెథడ్ లోపల అసింక్ ఆపరేషన్లను ఉపయోగించవద్దు. దానికి బదులుగా Symbol.asyncDisposeని ఉపయోగించండి.
  • using డిక్లరేషన్‌లు బ్లాక్-స్కోప్డ్ (block-scoped) అని గుర్తుంచుకోండి. ఒక if బ్లాక్ లోపల ఉన్న వనరు ఆ బ్లాక్ ముగిసినప్పుడు డిస్పోజ్ అవుతుంది, ఫంక్షన్ ముగిసినప్పుడు కాదు.

ఈ ప్యాటర్న్ చాలా తక్కువ రన్‌టైమ్ ఖర్చుతో (negligible runtime cost) భద్రతను అందిస్తుంది.

Source: https://dev.to/jsmanifest/typescript-using-keyword-and-explicit-resource-management-done-right-22pg