reqオブジェクトを変更せずにリクエスト全体にデータを渡し、すべてのレイヤーに渡す「スレッドセーフ」ソリューションが機能していることがわかりました。
そのため、req の開始時に req をバインドし、次の呼び出しで再利用できるcontinuation-local-storageパッケージがあります。しかし、非同期呼び出しのチェーンを使用しようとすると気分が悪くなります.CLSは「スレッドセーフ」ではなく、少数の同時リクエスト中に呼び出そうとすると失敗し、「コンテキスト」が失われます.
そのため、この問題を修正するcls-hookedパッケージがあり、リクエストの開始時に現在のコンテキスト バインディング リクエストを簡単にキャッチできます。
awilix (依存性注入フレームワーク) を使用する小さな例があり、「RequestContext」クラスを作成し、必要な場所で使用できるようにします。
RequestContext クラスを作成しましょう:
module.exports = class RequestContext {
 constructor(req, res, dependencies) {
 const { myService1, myService2 } = dependencies;    
 this.req = req;
 this.res = res;
}
getMyTestHeader() {
 return this.req.headers.testHeader;
}
シンプルな「リクエストラッパー」です。必要に応じてリクエスト、レスポンス、その他の依存関係を消費し、クラス外で使用する getMyTestHeader を提供します。
リクエストの開始時に (他のすべての前に) ミドルウェアを作成しましょう:
  //Registering our namespace. creating it one per app
  const clsNamespace = require('cls-hooked').createNamespace('my-per-request-session'); 
  app.use((req, res, next) => {
      // binding continuation-local-storage (cls-hooked) to request and response
      clsNamespace.bind(req);
      clsNamespace.bind(res);
      clsNamespace.run(() => {
      // save here req and res to use it later in requestContext instance, it will alive during request and could be picked up from DI as other dependencies
       clsNamespace.set('req', req);
       clsNamespace.set('res', res);
       next();
      });
  });
それでは、 awilix を使用して DI 呼び出しを登録しましょう。
container.register({  
requestContextProvider: asFunction(dependencies => ({
 getCurrentContext: () => {
  //retrieve res and req on each DI call "from current request"
  //also, clsNamespace should be the same as we registered before, on original code it is also registered using DI container.
  const req = dependencies.clsNamespace.get('req');
  const res = dependencies.clsNamespace.get('res');
  //and return our RequestContext (wrapper for req and res)
  return new RequestContext(req, res, dependencies);
 },
})),
そのため、requestContextProvider を関数として登録しています。これは、各 DI 依存関係呼び出しの各要求で、外部コンテキスト (cls) からの req および res でインスタンス化されます。その結果、次の方法で使用できます(たとえば、コントローラーで):
module.exports = (dependencies) => ({
 myControllerAction: async (req, res) => {
  const {requestContextProvider} = dependencies;
  const requestContext = requestContextProvider.getCurrentContext();
  //it will return header from req!
  const myHeader = requestContext.getMyTestHeader(); 
  res.status(200).json({ myHeader });
 },    
});
ご覧のとおり、すべてのレイヤー レベル (コントローラー/BLL/DAL/ヘルパーなど) で DI にアクセスできるすべての場所に "requestContext" があります。したがって、「スレッドセーフ」であり、テストが容易であり、すべての「中間」レイヤーを介して req オブジェクトをスローする必要はありません。
同意します。最良で簡単な例ではありませんが、誰かの役に立てば幸いです。