TypeScript using کی ورڈ اور Explicit Resource Management
پروڈکشن میں میموری لیکس (memory leaks) اکثر ایک ہی غلطی کی وجہ سے ہوتے ہیں: ڈویلپرز ریسورسز حاصل تو کر لیتے ہیں لیکن انہیں ریلیز (release) کرنے میں ناکام رہتے ہیں۔
ڈیٹا بیس کنکشنز غلطیوں کے بعد بھی کھلے رہ جاتے ہیں۔ فائل ہینڈلز سسٹم کے وسائل استعمال کرتے رہتے ہیں۔ WebSocket کلائنٹس مردہ سرورز سے جڑے رہتے ہیں۔ ایسا اس وقت ہوتا ہے جب آپ finally بلاکس میں دستی صفائی (manual cleanup) پر بھروسہ کرتے ہیں۔
TypeScript کا using کی ورڈ اس مسئلے کو حل کرتا ہے۔ یہ ECMAScript Explicit Resource Management تجویز کا حصہ ہے۔ یہ disposable پیٹرن کے ذریعے صفائی کی ضمانت دیتا ہے۔ جب کوئی ریسورس اپنے اسکوپ (scope) سے باہر نکلتا ہے، تو TypeScript خود بخود اس کا disposal میتھڈ چلا دیتا ہے۔
اب آپ کو دستی finally بلاکس کی ضرورت نہیں ہے۔ اب آپ صفائی کرنا نہیں بھولیں گے۔ اب آپ کے کنکشنز لیک نہیں ہوں گے۔
یہ کیسے کام کرتا ہے:
usingکی ورڈ اس بات کو یقینی بناتا ہے کہ جب ریسورسز اسکوپ سے باہر نکلیں تو ان کا disposal ہو جائے۔- Disposable ریسورسز سنکرونس (sync) کاموں کے لیے
Symbol.disposeیا اسینکرونس (async) کاموں کے لیےSymbol.asyncDisposeکو امپلیمنٹ کرتے ہیں۔ - TypeScript
usingڈیکلیریشنز کو ایک خودکار disposal stack کے ساتھtry-finallyبلاکس میں تبدیل کر دیتا ہے۔ - یہ پیٹرن جلد واپسی (early returns)، تھرو ہونے والے استثنائی حالات (exceptions)، یا بھولے ہوئے کوڈ کی وجہ سے ہونے والے لیکس کو روکتا ہے۔
کسی بھی ایسے ریسورس کے لیے using کا استعمال کریں جس کی ایک مقررہ مدت ہو، جیسے کہ ڈیٹا بیس کنکشنز، فائل ہینڈلز، لاکس، یا ٹائمرز۔
یہ میکانزم ایک disposal پروٹوکول استعمال کرتا ہے۔ آبجیکٹس ایک ایسا میتھڈ امپلیمنٹ کرتے ہیں جس کی کی (key) 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 ایک تیار کردہ (generated) finally بلاک میں چلتا ہے۔ یہ تب بھی چلتا ہے اگر فنکشن کوئی ایرر تھرو کرے یا جلد واپس (return) آ جائے۔
TypeScript ایک disposal stack برقرار رکھتا ہے۔ یہ ریسورسز کو ان کے حاصل کرنے کے الٹ ترتیب (reverse order) میں ڈسپوز کرتا ہے۔ یہ زیادہ تر صفائی کے لاجک کے لیے قدرتی انحصار کی ترتیب (dependency order) کے مطابق ہوتا ہے۔
اسینکرونس صفائی کے لیے، await using استعمال کریں۔ اس کے لیے ضروری ہے کہ ریسورس Symbol.asyncDispose کو امپلیمنٹ کرے۔ TypeScript آگے بڑھنے سے پہلے واپس آنے والے Promise کا انتظار (await) کرے گا۔
کامیابی کے لیے تین اصول:
- اپنے disposal میتھڈز کے اندر استثنا (exceptions) تھرو نہ کریں۔ اس کے بجائے ایررز کو اندرونی طور پر پکڑیں (catch کریں) اور لاگ کریں۔
- سنکرونس
Symbol.disposeمیتھڈ کے اندر اسینکرونس آپریشنز استعمال نہ کریں۔ اس کے بجائےSymbol.asyncDisposeاستعمال کریں۔ - یاد رکھیں کہ
usingڈیکلیریشنز بلاک اسکوپڈ (block-scoped) ہوتی ہیں۔ifبلاک کے اندر موجود ریسورس اس بلاک کے ختم ہونے پر ڈسپوز ہوتا ہے، نہ کہ فنکشن کے ختم ہونے پر۔
یہ پیٹرن نہ ہونے کے برابر رن ٹائم لاگت (runtime cost) کے ساتھ حفاظت فراہم کرتا ہے۔
Source: https://dev.to/jsmanifest/typescript-using-keyword-and-explicit-resource-management-done-right-22pg
