2017-12-13 9 views
0

TypeScriptで確定的なクリーンアップを達成するための慣習的な方法は何ですか?言い換えれば、C#のusing (IDisposable)やC++のRAIIに相当するものがありますか?TypeisのIDisposable/RAII?

finallyに貼ってもいいですか?


コンテキスト:SPAアプリケーション(オーレリア/ ASP.NETコアのWeb API)で、私は、データが現在のWeb APIからフェッチされている利用者に指示を与えるためにしようとしています。フェッチが完了したら、例外がスローされた場合でもUIの指示を削除したいと思います。私はあなたが常にすることができ、活字体にはusing文はありません

答えて

0

...再利用とクリーンな構文については、「RAIIクラス」(私は唐辛子にfinallyを使用してコードを持っていない)にそのをラップに探していますいずれにしてもtry-finallyに戻ってください。usingはC#の構文的な砂糖です。

もう1つの方法は、独自の機能を持つusingを作成することです。

interface IDisposableAsync { 
    dispose(): Promise<void> | void; 
} 
function usingAsync<T extends IDisposableAsync, T2 extends IDisposableAsync, T3 extends IDisposableAsync>(disposable: [T, T2, T3], action: (r: T, r2: T2, r3: T3) => Promise<void>): Promise<void>; 
function usingAsync<T extends IDisposableAsync, T2 extends IDisposableAsync>(disposable: [T, T2], action: (r: T, r2: T2) => Promise<void>): Promise<void>; 
function usingAsync<T extends IDisposableAsync>(disposable: T, action: (r: T) => Promise<void>): Promise<void>; 
function usingAsync(disposable: IDisposableAsync[], action: (...r: IDisposableAsync[]) => Promise<void>): Promise<void> 
async function usingAsync(disposable: IDisposableAsync | IDisposableAsync[], action: (...r: IDisposableAsync[]) => Promise<void>): Promise<void> { 
    let disposableArray = disposable instanceof Array ? disposable : [disposable]; 
    try { 
     await action(...disposableArray); 
    } finally { 
     for (let d of disposableArray) { 
      let result = d.dispose(); 
      if (result !== null) { 
       await result; 
      } 
     } 
    } 
} 

// Usage 
class UserNotify { dispose() { console.log("Done"); } } 
class Other { dispose() { console.log("Done Other"); } } 
function delay() { 
    return new Promise((r)=> setTimeout(() => { 
     r(); 
    }, 100)); 
} 
(async function() { 
    await usingAsync(new UserNotify(), async userNotify => { 
     await delay() 
     console.log("DoStuff"); 
    }) 

    await usingAsync([new UserNotify(), new Other()], async (userNotify, other) => { 
     await delay() 
     console.log("DoStuff"); 
    }) 
})(); 
:あなたは約束でそれを使用したい場合は

interface IDisposable { 
    dispose(); 
} 

function using<T extends IDisposable, 
    T2 extends IDisposable, 
    T3 extends IDisposable>(disposable: [T, T2, T3], action: (r: T, r2: T2, r3: T3) => void); 
function using<T extends IDisposable, T2 extends IDisposable>(disposable: [T, T2], action: (r: T, r2: T2) => void); 
function using<T extends IDisposable>(disposable: T, action: (r: T) => void); 
function using(disposable: IDisposable[], action: (...r: IDisposable[]) => void) 
function using(disposable: IDisposable | IDisposable[], action: (...r: IDisposable[]) => void) { 
    let disposableArray = disposable instanceof Array ? disposable : [disposable]; 
    try { 
     action(...disposableArray); 
    } finally { 
     disposableArray.forEach(d => d.dispose()); 
    } 
} 


// Usage 
class UserNotify { dispose() { console.log("Done"); } } 

class Other { dispose() { console.log("Done Other"); } } 

using(new UserNotify(), userNotify => { 
    console.log("DoStuff"); 
}) 
// It will type the arrow function parameter correctly for up to 3 parameters, but you can add more overloads above. 
using([new UserNotify(), new Other()], (userNotify, other) => { 
    console.log("DoStuff"); 
}) 

、あなたは使い捨てのリターンが約束とactionパラメータは、同様の約束を返すに非同期バージョンを作成することができます

関連する問題