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 method ਚਲਾ ਦਿੰਦਾ ਹੈ।

ਤੁਹਾਨੂੰ ਹੁਣ ਮੈਨੂਅਲ finally ਬਲਾਕਾਂ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ। ਤੁਸੀਂ ਹੁਣ ਸਫਾਈ ਕਰਨਾ ਨਹੀਂ ਭੁੱਲੋਗੇ। ਤੁਸੀਂ ਹੁਣ ਕਨੈਕਸ਼ਨਾਂ ਨੂੰ ਲੀਕ ਨਹੀਂ ਕਰੋਗੇ।

ਇਹ ਕਿਵੇਂ ਕੰਮ ਕਰਦਾ ਹੈ:

  • using ਕੀਵਰਡ ਇਹ ਯਕੀਨੀ ਬਣਾਉਂਦਾ ਹੈ ਕਿ ਜਦੋਂ ਸਰੋਤ ਕਿਸੇ ਸਕੋਪ ਤੋਂ ਬਾਹਰ ਨਿਕਲਦੇ ਹਨ ਤਾਂ ਉਹਨਾਂ ਦੀ disposal ਹੋ ਜਾਵੇ।
  • Disposable ਸਰੋਤ ਸਿੰਕ (sync) ਕੰਮਾਂ ਲਈ Symbol.dispose ਜਾਂ ਐਸਿੰਕ (async) ਕੰਮਾਂ ਲਈ Symbol.asyncDispose ਨੂੰ ਇੰਪਲੀਮੈਂਟ ਕਰਦੇ ਹਨ।
  • TypeScript using ਡਿਕਲੇਰੇਸ਼ਨਾਂ ਨੂੰ ਇੱਕ ਆਟੋਮੈਟਿਕ disposal stack ਦੇ ਨਾਲ try-finally ਬਲਾਕਾਂ ਵਿੱਚ ਬਦਲ ਦਿੰਦਾ ਹੈ।
  • ਇਹ ਪੈਟਰਨ ਅਰਥੀ ਰਿਟਰਨ (early returns), ਸੁੱਤੇ ਹੋਏ ਐਕਸੈਪਸ਼ਨਾਂ (thrown exceptions), ਜਾਂ ਭੁੱਲੇ ਹੋਏ ਕੋਡ ਕਾਰਨ ਹੋਣ ਵਾਲੇ ਲੀਕਸ ਨੂੰ ਰੋਕਦਾ ਹੈ।

ਕਿਸੇ ਵੀ ਅਜਿਹੇ ਸਰੋਤ ਲਈ using ਦੀ ਵਰਤੋਂ ਕਰੋ ਜਿਸਦੀ ਇੱਕ ਨਿਸ਼ਚਿਤ ਉਮਰ (lifetime) ਹੋਵੇ, ਜਿਵੇਂ ਕਿ ਡਾਟਾਬੇਸ ਕਨੈਕਸ਼ਨ, ਫਾਈਲ ਹੈਂਡਲ, ਲੌਕਸ (locks), ਜਾਂ ਟਾਈਮਰ।

ਇਹ ਮਕੈਨਿਜ਼ਮ ਇੱਕ disposal ਪ੍ਰੋਟੋਕੋਲ ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ। ਆਬਜੈਕਟ Symbol.dispose ਦੁਆਰਾ ਕੀਅਡ (keyed) ਇੱਕ ਮੈਥਡ ਨੂੰ ਇੰਪਲੀਮੈਂਟ ਕਰਦੇ ਹਨ। ਜਦੋਂ ਸਕੋਪ ਨਾਰਮਲ ਕੰਪਲੀਸ਼ਨ, ਰਿਟਰਨ, ਜਾਂ ਕਿਸੇ ਐਕਸੈਪਸ਼ਨ ਰਾਹੀਂ ਬਾਹਰ ਨਿਕਲਦਾ ਹੈ, ਤਾਂ 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) ਵਿੱਚ ਡਿਸਪੋਜ਼ ਕਰਦਾ ਹੈ ਜਿਸ ਕ੍ਰਮ ਵਿੱਚ ਤੁਸੀਂ ਉਹਨਾਂ ਨੂੰ ਪ੍ਰਾਪਤ ਕੀਤਾ ਸੀ। ਇਹ ਜ਼ਿਆਦਾਤਰ ਸਫਾਈ ਲੌਜਿਕ (cleanup logic) ਲਈ ਕੁਦਰਤੀ ਨਿਰਭਰਤਾ ਕ੍ਰਮ (dependency order) ਨਾਲ ਮੇਲ ਖਾਂਦਾ ਹੈ।

ਐਸਿੰਕ੍ਰੋਨਸ (asynchronous) ਸਫਾਈ ਲਈ, await using ਦੀ ਵਰਤੋਂ ਕਰੋ। ਇਸ ਲਈ ਸਰੋਤ ਦਾ Symbol.asyncDispose ਨੂੰ ਇੰਪਲੀਮੈਂਟ ਕਰਨਾ ਜ਼ਰੂਰੀ ਹੈ। TypeScript ਅੱਗੇ ਵਧਣ ਤੋਂ ਪਹਿਲਾਂ ਵਾਪਸ ਕੀਤੇ Promise ਦੀ ਉਡੀਕ (await) ਕਰੇਗਾ।

ਸਫਲਤਾ ਲਈ ਤਿੰਨ ਨਿਯਮ:

  • ਆਪਣੇ disposal ਮੈਥਡਾਂ ਦੇ ਅੰਦਰ ਐਕਸੈਪਸ਼ਨਾਂ ਨਾ ਸੁੱਟੋ। ਇਸਦੀ ਬਜਾਏ ਗਲਤੀਆਂ ਨੂੰ ਅੰਦਰੂਨੀ ਤੌਰ 'ਤੇ ਕੈਚ (catch) ਅਤੇ ਲੌਗ (log) ਕਰੋ।
  • ਸਿੰਕ੍ਰੋਨਸ Symbol.dispose ਮੈਥਡ ਦੇ ਅੰਦਰ ਐਸਿੰਕ (async) ਆਪਰੇਸ਼ਨਾਂ ਦੀ ਵਰਤੋਂ ਨਾ ਕਰੋ। ਇਸਦੀ ਬਜਾਏ Symbol.asyncDispose ਦੀ ਵਰਤੋਂ ਕਰੋ।
  • ਯਾਦ ਰੱਖੋ ਕਿ using ਡਿਕਲੇਰੇਸ਼ਨਾਂ ਬਲਾਕ-ਸਕੋਪਡ (block-scoped) ਹੁੰਦੀਆਂ ਹਨ। ਇੱਕ if ਬਲਾਕ ਦੇ ਅੰਦਰ ਇੱਕ ਸਰੋਤ ਉਦੋਂ ਡਿਸਪੋਜ਼ ਹੁੰਦਾ ਹੈ ਜਦੋਂ ਉਹ ਬਲਾਕ ਖਤਮ ਹੁੰਦਾ ਹੈ, ਨਾ ਕਿ ਉਦੋਂ ਜਦੋਂ ਫੰਕਸ਼ਨ ਖਤਮ ਹੁੰਦਾ ਹੈ।

ਇਹ ਪੈਟਰਨ ਨਿਗਣਯੋਗ (negligible) ਰਨਟਾਈਮ ਲਾਗਤ ਦੇ ਨਾਲ ਸੁਰੱਖਿਆ ਪ੍ਰਦਾਨ ਕਰਦਾ ਹੈ।

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