0

我想爲打字稿中的命名空間編寫中間件。所以當命名空間中的任何函數被調用時,中間件應該觸發並檢查是否可以執行預期的函數。例如:如何爲打字稿命名空間中的函數編寫中間件

namespace Foo.Bar { 
    function middleware(next) { 
    if (enabled) next(); 
    } 
    export function baz() { 
    // Do Something 
    } 
} 

如果我打電話給巴茲Foo.Bar.baz(),我希望我的中間件方法首先觸發。 如果是模塊,我可以導出的函數對象是這樣的:

export {baz: middleware} 

但命名空間不會允許這樣做。有什麼建議麼?

+0

你能在這個問題 – marvel308

+0

''命名空間Foo.Bar { applyMiddleWare(下){ 如果(啓用)NE提供一個例子XT(); } 導出功能觸發(){// 因此,一些 }} '' 因此,當觸發方法被調用時,我希望有一箇中間件功能首先執行。中間件將決定是否執行觸發器功能。 –

+0

這個問題很快就會被解決,除非你用更好的解釋和代碼編輯它。 –

回答

1

如果你行的一些「髒髒的」 JS類編碼,那麼接下來的做法可能會幫助您:

namespace Foo.Bar { 
    export function middleware(next) { 
     alert("middleware"); 
     next(); 
    } 
    export function baz() { 
     alert("baz"); 
     // Do Something 
    } 
} 

// Simple call 
Foo.Bar.baz(); 

// "Middleware magic" 
const origMethod = Foo.Bar.baz; 
Foo.Bar.baz =() => { 
    Foo.Bar.middleware(origMethod); 
} 
// Middleware call 
Foo.Bar.baz(); 

它可以在TS playground site進行測試。

+0

這太好了。但我不認爲這是我的應用程序的最佳方法。我們可以維護名字空間'Foo.Bar'並且有一個導出函數對象的類嗎? –

+0

如果您需要在每次有人調用Foo.Bar.baz()方法時執行原始代碼之前運行代碼,除了創建新函數而不是原始Foo.Bar.baz之外,沒有其他方法。 –

0

以下是使用靜態類和方法decorators的示例。

foo.ts

// method decorator  
function middleware() { 
    return function(target: any, propertyKey: string) { 
     // exec middleware 
     console.log('middleware') 
    } 
} 

export namespace Foo { 

    export class Bar { 
     constructor() { 
      throw new Error('Instantiating is not allowed'); 
     } 

     @middleware() 
     static baz() { 
      console.log('after middleware'); 
     } 
    } 
} 

這仍然會保持你的命名空間約定。

index.ts

import { Foo } from './foo'; 

Foo.Bar.baz(); 

該中間件將觸發方法baz被調用之前。但是,如果你的中間件是async,你需要裝飾的方法,以等待要完成的中間件,可以中間件更改爲類似如下:

function middleware() { 
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { 
     let fn = descriptor.value; 

     return { 
      configurable: true, 
      get() { 
       return() => { 
        console.log('middleware'); 

        wait(1000).then(() => wait(1000)).then(() => fn.call()); 
       } 
      } 
     } 
    }; 
} 

function wait(millis: number) { 
    console.log(`wait ${millis}ms`); 

    return new Promise<void>(resolve => { 
     setTimeout(resolve, millis); 
    }); 
} 

或者,如果你喜歡asyncawait,你可以改變get函數返回Promise<void>類型,而不是一個功能:

get() { 
    return async() => { 
     console.log('middleware') 

     await wait(1000); 

     await wait(1000); 

     fn.call(); 
    } 
}