TypeScriptの using キーワードと明示的なリソース管理 (Explicit Resource Management)
本番環境でのメモリリークは、多くの場合、ある一つのミスに起因します。それは、開発者がリソースを取得したものの、それを解放し忘れることです。
エラーが発生した後もデータベース接続が開いたままになったり、ファイルハンドルがシステムリソースを消費し続けたり、WebSocketクライアントが切断されたサーバーに接続されたままになったりします。これは、finally ブロック内での手動のクリーンアップに依存している場合に発生します。
TypeScriptの using キーワードはこの問題を解決します。これは ECMAScript の Explicit Resource Management プロポーザルの一部です。このキーワードは、Disposable パターンを通じてクリーンアップを保証します。リソースがそのスコープを抜けると、TypeScript はその破棄(disposal)メソッドを自動的に実行します。
もはや手動の finally ブロックは必要ありません。クリーンアップを忘れることも、接続をリークさせることもなくなります。
仕組み:
usingキーワードは、リソースがスコープを抜ける際に破棄を保証します。- Disposable なリソースは、同期タスクには
Symbol.disposeを、非同期タスクにはSymbol.asyncDisposeを実装します。 - TypeScript は
using宣言を、自動的な破棄スタックを持つtry-finallyブロックに変換します。 - このパターンにより、早期リターン、例外の送出、あるいはコードの書き忘れによって引き起こされるリークを防ぐことができます。
データベース接続、ファイルハンドル、ロック、タイマーなど、寿命が決まっているあらゆるリソースに using を使用してください。
このメカニズムは破棄プロトコル(disposal protocol)を使用します。オブジェクトは Symbol.dispose をキーとするメソッドを実装します。通常の完了、return、または例外によってスコープを抜ける際、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 は破棄スタックを保持します。リソースは取得した時とは逆の順序で破棄されます。これは、ほとんどのクリーンアップロジックにおける自然な依存関係の順序と一致します。
非同期のクリーンアップには await using を使用します。これには、リソースが Symbol.asyncDispose を実装している必要があります。TypeScript は処理を続行する前に、返された Promise を await します。
成功させるための3つのルール:
- 破棄メソッド内で例外をスローしないでください。代わりに、内部でエラーをキャッチしてログに記録してください。
- 同期的な
Symbol.disposeメソッド内で非同期操作を行わないでください。代わりにSymbol.asyncDisposeを使用してください。 using宣言はブロックスコープであることを忘れないでください。ifブロック内のリソースは、関数が終了した時ではなく、そのブロックが終了した時に破棄されます。
このパターンは、実行時のコストをほとんどかけずに安全性を提供します。
Source: https://dev.to/jsmanifest/typescript-using-keyword-and-explicit-resource-management-done-right-22pg
