کلمه کلیدی using در TypeScript و مدیریت صریح منابع (Explicit Resource Management)
نشت حافظه (Memory leaks) در محیط عملیاتی اغلب از یک خطا ناشی میشود: توسعهدهندگان منابع را دریافت میکنند اما در آزادسازی آنها شکست میخورند.
اتصالات پایگاه داده پس از بروز خطا باز میمانند. هندلهای فایل (File handles) منابع سیستم را مصرف میکنند. کلاینتهای WebSocket به سرورهای قطع شده متصل میمانند. این اتفاق زمانی رخ میدهد که شما برای پاکسازی به بلوکهای finally دستی تکیه میکنید.
کلمه کلیدی using در TypeScript این مشکل را حل میکند. این قابلیت بخشی از پیشنهاد مدیریت صریح منابع (Explicit Resource Management) در ECMAScript است. این ویژگی، پاکسازی را از طریق الگوی قابلدفع (disposable pattern) تضمین میکند. وقتی یک منبع از محدوده (scope) خود خارج میشود، TypeScript متد آزادسازی (disposal method) آن را بهطور خودکار اجرا میکند.
دیگر نیازی به بلوکهای finally دستی ندارید. دیگر پاکسازی را فراموش نمیکنید. دیگر باعث نشت اتصالات نمیشوید.
نحوه عملکرد:
- کلمه کلیدی
usingتضمین میکند که هنگام خروج منابع از یک محدوده (scope)، آزادسازی انجام شود. - منابع قابلدفع (Disposable resources) برای وظایف همگام (sync) از
Symbol.disposeو برای وظایف ناهمگام (async) ازSymbol.asyncDisposeاستفاده میکنند. - TypeScript اعلانهای
usingرا به بلوکهایtry-finallyهمراه با یک پشته آزادسازی (disposal stack) خودکار تبدیل میکند. - این الگو از نشتهای ناشی از بازگشتهای زودهنگام (early returns)، استثناهای پرتاب شده (thrown exceptions) یا کدهای فراموش شده جلوگیری میکند.
از using برای هر منبعی با طول عمر مشخص، مانند اتصالات پایگاه داده، هندلهای فایل، قفلها (locks) یا تایمرها استفاده کنید.
این مکانیسم از یک پروتکل آزادسازی استفاده میکند. اشیاء متدی را پیادهسازی میکنند که با کلید Symbol.dispose مشخص شده است. وقتی محدوده از طریق اتمام عادی، یک دستور return یا یک استثنا (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);
}
فرآیند آزادسازی در یک بلوک finally تولید شده اجرا میشود. این فرآیند حتی اگر تابع خطایی پرتاب کند یا زودتر از موعد بازگردد، اجرا میشود.
TypeScript یک پشته آزادسازی را مدیریت میکند. منابع را به ترتیب معکوسِ نحوه دریافت آنها آزاد میکند. این کار با ترتیب وابستگی طبیعی در اکثر منطقهای پاکسازی مطابقت دارد.
برای پاکسازی ناهمگام (asynchronous)، از await using استفاده کنید. این کار مستلزم آن است که منبع، Symbol.asyncDispose را پیادهسازی کند. TypeScript قبل از ادامه کار، منتظر (await) Promise بازگشتی میماند.
سه قانون برای موفقیت:
- داخل متدهای آزادسازی خود استثنا (exception) پرتاب نکنید. در عوض، خطاها را در داخل متد مدیریت (catch) و ثبت (log) کنید.
- از عملیات ناهمگام (async) در یک متد همگامِ
Symbol.disposeاستفاده نکنید. در عوض ازSymbol.asyncDisposeاستفاده کنید. - به یاد داشته باشید که اعلانهای
usingدارای محدوده بلوکی (block-scoped) هستند. منبعی که داخل یک بلوکifقرار دارد، زمانی که آن بلوک تمام شود آزاد میشود، نه زمانی که تابع تمام شود.
این الگو امنیت را با هزینه زمان اجرای (runtime cost) ناچیز فراهم میکند.
منبع: https://dev.to/jsmanifest/typescript-using-keyword-and-explicit-resource-management-done-right-22pg
