TypeScript using ಕೀವರ್ಡ್ ಮತ್ತು Explicit Resource Management

ಪ್ರೊಡಕ್ಷನ್‌ನಲ್ಲಿ ಮೆಮೊರಿ ಲೀಕ್‌ಗಳು (Memory leaks) ಹೆಚ್ಚಾಗಿ ಒಂದು ತಪ್ಪಿನಿಂದ ಉಂಟಾಗುತ್ತವೆ: ಡೆವಲಪರ್‌ಗಳು ಸಂಪನ್ಮೂಲಗಳನ್ನು (resources) ಪಡೆದುಕೊಳ್ಳುತ್ತಾರೆ ಆದರೆ ಅವುಗಳನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲು ವಿಫಲರಾಗುತ್ತಾರೆ.

ದತ್ತಸಂಚಯನ (Database) ಸಂಪರ್ಕಗಳು ದೋಷಗಳ ನಂತರವೂ ತೆರೆದೇ ಇರುತ್ತವೆ. ಫೈಲ್ ಹ್ಯಾಂಡಲ್‌ಗಳು (File handles) ಸಿಸ್ಟಮ್ ಸಂಪನ್ಮೂಲಗಳನ್ನು ಬಳಸುತ್ತವೆ. WebSocket ಕ್ಲೈಂಟ್‌ಗಳು ಸ್ಥಗಿತಗೊಂಡ ಸರ್ವರ್‌ಗಳಿಗೆ ಸಂಪರ್ಕ ಹೊಂದಿಯೇ ಇರುತ್ತವೆ. ನೀವು finally ಬ್ಲಾಕ್‌ಗಳಲ್ಲಿ ಮ್ಯಾನುಯಲ್ ಕ್ಲೀನಪ್ (manual cleanup) ಮೇಲೆ ಅವಲಂಬಿತರಾದಾಗ ಹೀಗಾಗುತ್ತದೆ.

TypeScript ನ using ಕೀವರ್ಡ್ ಇದನ್ನು ಪರಿಹರಿಸುತ್ತದೆ. ಇದು ECMAScript Explicit Resource Management ಪ್ರಸ್ತಾವನೆಯ ಭಾಗವಾಗಿದೆ. ಇದು disposable pattern ಮೂಲಕ ಕ್ಲೀನಪ್ ಅನ್ನು ಖಚಿತಪಡಿಸುತ್ತದೆ. ಒಂದು ಸಂಪನ್ಮೂಲವು ತನ್ನ ಸ್ಕೋಪ್‌ನಿಂದ (scope) ಹೊರಬಂದಾಗ, TypeScript ಅದರ disposal method ಅನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಚಲಾಯಿಸುತ್ತದೆ.

ನಿಮಗೆ ಇನ್ನು ಮುಂದೆ ಮ್ಯಾನುಯಲ್ finally ಬ್ಲಾಕ್‌ಗಳ ಅಗತ್ಯವಿಲ್ಲ. ನೀವು ಇನ್ನು ಮುಂದೆ ಕ್ಲೀನಪ್ ಮಾಡುವುದನ್ನು ಮರೆಯುವುದಿಲ್ಲ. ನೀವು ಇನ್ನು ಮುಂದೆ ಕನೆಕ್ಷನ್‌ಗಳನ್ನು ಲೀಕ್ ಮಾಡುವುದಿಲ್ಲ.

ಇದು ಹೇಗೆ ಕೆಲಸ ಮಾಡುತ್ತದೆ:

  • using ಕೀವರ್ಡ್ ಸಂಪನ್ಮೂಲಗಳು ಸ್ಕೋಪ್‌ನಿಂದ ಹೊರಬಂದಾಗ ಅವುಗಳ ವಿಲೇವಾರಿಯನ್ನು (disposal) ಖಚಿತಪಡಿಸುತ್ತದೆ.
  • Disposable ಸಂಪನ್ಮೂಲಗಳು ಸಿಂಕ್ (sync) ಕಾರ್ಯಗಳಿಗಾಗಿ Symbol.dispose ಅಥವಾ ಅಸಿಂಕ್ (async) ಕಾರ್ಯಗಳಿಗಾಗಿ Symbol.asyncDispose ಅನ್ನು ಅನುಷ್ಠಾನಗೊಳಿಸುತ್ತವೆ.
  • TypeScript using ಘೋಷಣೆಗಳನ್ನು (declarations) ಸ್ವಯಂಚಾಲಿತ disposal stack ಹೊಂದಿರುವ try-finally ಬ್ಲಾಕ್‌ಗಳಾಗಿ ಪರಿವರ್ತಿಸುತ್ತದೆ.
  • ಈ ಪ್ಯಾಟರ್ನ್ ಆರಂಭಿಕ ರಿಟರ್ನ್ (early returns), ಎಸೆತದ ವಿನಾಯಿತಿಗಳು (thrown exceptions) ಅಥವಾ ಮರೆತುಹೋದ ಕೋಡ್‌ನಿಂದ ಉಂಟಾಗುವ ಲೀಕ್‌ಗಳನ್ನು ತಡೆಯುತ್ತದೆ.

ಡೇಟಾಬೇಸ್ ಕನೆಕ್ಷನ್‌ಗಳು, ಫೈಲ್ ಹ್ಯಾಂಡಲ್‌ಗಳು, ಲಾಕ್‌ಗಳು ಅಥವಾ ಟೈಮರ್‌ಗಳಂತಹ ನಿರ್ದಿಷ್ಟ ಜೀವಿತಾವಧಿಯನ್ನು ಹೊಂದಿರುವ ಯಾವುದೇ ಸಂಪನ್ಮೂಲಕ್ಕಾಗಿ using ಅನ್ನು ಬಳಸಿ.

ಈ ಕಾರ್ಯವಿಧಾನವು disposal protocol ಅನ್ನು ಬಳಸುತ್ತದೆ. ಆಬ್ಜೆಕ್ಟ್‌ಗಳು Symbol.dispose ಮೂಲಕ ಗುರುತಿಸಲ್ಪಟ್ಟ ಒಂದು ಮೆಥಡ್ ಅನ್ನು ಅನುಷ್ಠಾನಗೊಳಿಸುತ್ತವೆ. ಸ್ಕೋಪ್ ಸಾಮಾನ್ಯ ಪೂರ್ಣತೆ, ರಿಟರ್ನ್ ಅಥವಾ ವಿನಾಯಿತಿಯ (exception) ಮೂಲಕ ಹೊರಬಂದಾಗ, 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);
}

Disposal ಅನ್ನು ಜನರೇಟ್ ಮಾಡಲಾದ finally ಬ್ಲಾಕ್‌ನಲ್ಲಿ ಚಲಾಯಿಸಲಾಗುತ್ತದೆ. ಫಂಕ್ಷನ್ ದೋಷವನ್ನು ಎಸೆದರೂ ಅಥವಾ ಬೇಗನೆ ರಿಟರ್ನ್ ಆದರೂ ಇದು ಚಲಿಸುತ್ತದೆ.

TypeScript ಒಂದು disposal stack ಅನ್ನು ನಿರ್ವಹಿಸುತ್ತದೆ. ನೀವು ಸಂಪನ್ಮೂಲಗಳನ್ನು ಪಡೆದ ಕ್ರಮದ ವಿರುದ್ಧ ಕ್ರಮದಲ್ಲಿ (reverse order) ಅದು ಅವುಗಳನ್ನು ವಿಲೇವಾರಿ ಮಾಡುತ್ತದೆ. ಇದು ಹೆಚ್ಚಿನ ಕ್ಲೀನಪ್ ಲಾಜಿಕ್‌ನ ನೈಸರ್ಗಿಕ ಅವಲಂಬನೆಯ ಕ್ರಮಕ್ಕೆ ಹೊಂದಿಕೆಯಾಗುತ್ತದೆ.

ಅಸಿಂಕ್ರೋನಸ್ (asynchronous) ಕ್ಲೀನಪ್‌ಗಾಗಿ, await using ಬಳಸಿ. ಇದಕ್ಕೆ ಸಂಪನ್ಮೂಲವು Symbol.asyncDispose ಅನ್ನು ಅನುಷ್ಠಾನಗೊಳಿಸಬೇಕಾಗುತ್ತದೆ. TypeScript ಮುಂದುವರಿಯುವ ಮೊದಲು ರಿಟರ್ನ್ ಆದ Promise ಅನ್ನು ಕಾಯುತ್ತದೆ (await ಮಾಡುತ್ತದೆ).

ಯಶಸ್ಸಿಗಾಗಿ ಮೂರು ನಿಯಮಗಳು:

  • ನಿಮ್ಮ disposal ಮೆಥಡ್‌ಗಳ ಒಳಗೆ ವಿನಾಯಿತಿಗಳನ್ನು (exceptions) ಎಸೆಯಬೇಡಿ. ಬದಲಾಗಿ ದೋಷಗಳನ್ನು ಒಳಗಡೆಯೇ ಕ್ಯಾಚ್ (catch) ಮಾಡಿ ಮತ್ತು ಲಾಗ್ (log) ಮಾಡಿ.
  • ಸಿಂಕ್ರೋನಸ್ Symbol.dispose ಮೆಥಡ್‌ನ ಒಳಗೆ ಅಸಿಂಕ್ ಆಪರೇಷನ್‌ಗಳನ್ನು ಬಳಸಬೇಡಿ. ಬದಲಾಗಿ Symbol.asyncDispose ಬಳಸಿ.
  • using ಘೋಷಣೆಗಳು block-scoped ಆಗಿರುತ್ತವೆ ಎಂಬುದನ್ನು ನೆನಪಿಡಿ. if ಬ್ಲಾಕ್‌ನ ಒಳಗಿರುವ ಸಂಪನ್ಮೂಲವು ಆ ಬ್ಲಾಕ್ ಮುಗಿದಾಗ ವಿಲೇವಾರಿಯಾಗುತ್ತದೆ, ಫಂಕ್ಷನ್ ಮುಗಿದಾಗ ಅಲ್ಲ.

ಈ ಪ್ಯಾಟರ್ನ್ ಅತ್ಯಲ್ಪ ರನ್‌ಟೈಮ್ ವೆಚ್ಚದೊಂದಿಗೆ ಸುರಕ್ಷತೆಯನ್ನು ಒದಗಿಸುತ್ತದೆ.

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