e22m4u 2 недель назад
Родитель
Сommit
351513113b
2 измененных файлов с 115 добавлено и 56 удалено
  1. 46 20
      dist/cjs/index.cjs
  2. 69 36
      src/hooks/hook-invoker.js

+ 46 - 20
dist/cjs/index.cjs

@@ -885,7 +885,11 @@ var HookRegistry = _HookRegistry;
 // src/hooks/hook-invoker.js
 var _HookInvoker = class _HookInvoker extends DebuggableService {
   /**
-   * Invoke and continue until value received.
+   * Последовательно вызывает глобальные хуки и хуки маршрута указанного
+   * типа, пока один из них не вернет отличное от undefined и null значение
+   * или не отправит HTTP-ответ. Метод выполняет хуки в синхронном режиме
+   * для улучшения производительности. Если один из хуков возвращает Promise,
+   * выполнение оставшейся части цепочки переключается в асинхронный режим.
    *
    * @param {Route} route
    * @param {string} hookType
@@ -934,31 +938,53 @@ var _HookInvoker = class _HookInvoker extends DebuggableService {
       }
       if (result != null) {
         if (isPromise(result)) {
-          return (async () => {
-            let asyncResult = await result;
-            if (isResponseSent(response)) {
-              return response;
-            }
-            if (asyncResult != null) {
-              return asyncResult;
-            }
-            for (let j = i + 1; j < hooks.length; j++) {
-              asyncResult = await hooks[j](...args);
-              if (isResponseSent(response)) {
-                return response;
-              }
-              if (asyncResult != null) {
-                return asyncResult;
-              }
-            }
-            return;
-          })();
+          return this._continueHooksInvocationAsync(
+            hooks,
+            i + 1,
+            result,
+            response,
+            args
+          );
         }
         return result;
       }
     }
     return;
   }
+  /**
+   * Асинхронно продолжает выполнение цепочки хуков, начиная с указанного
+   * индекса. Данный метод вызывается, когда хук в основном синхронном цикле
+   * возвращает Promise. Метод ожидает разрешения начального Promise, а затем
+   * последовательно выполняет оставшиеся хуки в асинхронном режиме, следуя
+   * той же логике прерывания (при получении значения или отправке ответа),
+   * что и основной метод.
+   *
+   * @param {Function[]} hooks
+   * @param {number} startIndex
+   * @param {Promise} initialPromise
+   * @param {import('http').ServerResponse} response
+   * @param {*} args
+   * @returns {Promise<*>}
+   */
+  async _continueHooksInvocationAsync(hooks, startIndex, initialPromise, response, args) {
+    let result = await initialPromise;
+    if (isResponseSent(response)) {
+      return response;
+    }
+    if (result != null) {
+      return result;
+    }
+    for (let i = startIndex; i < hooks.length; i++) {
+      result = await hooks[i](...args);
+      if (isResponseSent(response)) {
+        return response;
+      }
+      if (result != null) {
+        return result;
+      }
+    }
+    return;
+  }
 };
 __name(_HookInvoker, "HookInvoker");
 var HookInvoker = _HookInvoker;

+ 69 - 36
src/hooks/hook-invoker.js

@@ -9,7 +9,11 @@ import {HookRegistry, RouterHookType} from './hook-registry.js';
  */
 export class HookInvoker extends DebuggableService {
   /**
-   * Invoke and continue until value received.
+   * Последовательно вызывает глобальные хуки и хуки маршрута указанного
+   * типа, пока один из них не вернет отличное от undefined и null значение
+   * или не отправит HTTP-ответ. Метод выполняет хуки в синхронном режиме
+   * для улучшения производительности. Если один из хуков возвращает Promise,
+   * выполнение оставшейся части цепочки переключается в асинхронный режим.
    *
    * @param {Route} route
    * @param {string} hookType
@@ -87,41 +91,13 @@ export class HookInvoker extends DebuggableService {
         // выполнение переключается в асинхронный режим, начиная
         // с индекса следующего хука
         if (isPromise(result)) {
-          return (async () => {
-            // ожидание Promise, который был получен
-            // на предыдущем шаге (в синхронном режиме)
-            let asyncResult = await result;
-            // если ответ уже отправлен,
-            // то возвращается ServerResponse
-            if (isResponseSent(response)) {
-              return response;
-            }
-            // если Promise разрешился значением отличным
-            // от undefined и null, то данное значение
-            // возвращается в качестве результата
-            if (asyncResult != null) {
-              return asyncResult;
-            }
-            // продолжение вызова хуков начиная
-            // со следующего индекса (асинхронно)
-            for (let j = i + 1; j < hooks.length; j++) {
-              // с этого момента все синхронные
-              // хуки выполняются как асинхронные
-              asyncResult = await hooks[j](...args);
-              // если ответ уже отправлен,
-              // то возвращается ServerResponse
-              if (isResponseSent(response)) {
-                return response;
-              }
-              // если хук вернул значение отличное
-              // от undefined и null, то данное значение
-              // возвращается в качестве результата
-              if (asyncResult != null) {
-                return asyncResult;
-              }
-            }
-            return;
-          })();
+          return this._continueHooksInvocationAsync(
+            hooks,
+            i + 1,
+            result,
+            response,
+            args,
+          );
         }
         // если синхронный хук вернул значение отличное
         // от undefined и null, то данное значение
@@ -133,4 +109,61 @@ export class HookInvoker extends DebuggableService {
     // и не вернули значения
     return;
   }
+
+  /**
+   * Асинхронно продолжает выполнение цепочки хуков, начиная с указанного
+   * индекса. Данный метод вызывается, когда хук в основном синхронном цикле
+   * возвращает Promise. Метод ожидает разрешения начального Promise, а затем
+   * последовательно выполняет оставшиеся хуки в асинхронном режиме, следуя
+   * той же логике прерывания (при получении значения или отправке ответа),
+   * что и основной метод.
+   *
+   * @param {Function[]} hooks
+   * @param {number} startIndex
+   * @param {Promise} initialPromise
+   * @param {import('http').ServerResponse} response
+   * @param {*} args
+   * @returns {Promise<*>}
+   */
+  async _continueHooksInvocationAsync(
+    hooks,
+    startIndex,
+    initialPromise,
+    response,
+    args,
+  ) {
+    // ожидание Promise, который был получен
+    // на предыдущем шаге (в синхронном режиме)
+    let result = await initialPromise;
+    // если ответ уже отправлен,
+    // то возвращается ServerResponse
+    if (isResponseSent(response)) {
+      return response;
+    }
+    // если Promise разрешился значением отличным
+    // от undefined и null, то данное значение
+    // возвращается в качестве результата
+    if (result != null) {
+      return result;
+    }
+    // продолжение вызова хуков начиная
+    // со следующего индекса (асинхронно)
+    for (let i = startIndex; i < hooks.length; i++) {
+      // с этого момента все синхронные
+      // хуки выполняются как асинхронные
+      result = await hooks[i](...args);
+      // если ответ уже отправлен,
+      // то возвращается ServerResponse
+      if (isResponseSent(response)) {
+        return response;
+      }
+      // если хук вернул значение отличное
+      // от undefined и null, то данное значение
+      // возвращается в качестве результата
+      if (result != null) {
+        return result;
+      }
+    }
+    return;
+  }
 }