diff --git a/Build/Sources/TypeScript/core/Resources/Public/TypeScript/DocumentService.ts b/Build/Sources/TypeScript/core/Resources/Public/TypeScript/DocumentService.ts
index 694c794fac82c7f5a4152d8342caaa193e31910c..80b9f5f655f7fce7db6c0779e9d12d7790a3bb65 100644
--- a/Build/Sources/TypeScript/core/Resources/Public/TypeScript/DocumentService.ts
+++ b/Build/Sources/TypeScript/core/Resources/Public/TypeScript/DocumentService.ts
@@ -16,42 +16,18 @@
  * @exports TYPO3/CMS/Core/DocumentService
  */
 class DocumentService {
-  private readonly windowRef: Window;
-  private readonly documentRef: Document;
+  private promise: Promise<Document> = null;
 
-  /**
-   * @param {Window} windowRef
-   * @param {Document} documentRef
-   */
-  constructor(windowRef: Window = window, documentRef: Document = document) {
-    this.windowRef = windowRef;
-    this.documentRef = documentRef;
+  public ready(): Promise<Document> {
+    return this.promise ?? (this.promise = this.createPromise());
   }
 
-  ready(): Promise<Document> {
-    return new Promise<Document>((resolve: Function, reject: Function) => {
-      if (this.documentRef.readyState === 'complete') {
-        resolve(this.documentRef);
-      } else {
-        // timeout & reject after 30 seconds
-        const timer = setTimeout((): void => {
-          clearListeners();
-          reject(this.documentRef);
-        }, 30000);
-        const clearListeners = (): void => {
-          this.windowRef.removeEventListener('load', delegate);
-          this.documentRef.removeEventListener('DOMContentLoaded', delegate);
-        };
-        const delegate = (): void => {
-          clearListeners();
-          clearTimeout(timer);
-          resolve(this.documentRef);
-        };
-        this.windowRef.addEventListener('load', delegate);
-        this.documentRef.addEventListener('DOMContentLoaded', delegate);
-      }
-
-    });
+  private async createPromise(): Promise<Document> {
+    if (document.readyState !== 'loading') {
+      return document;
+    }
+    await new Promise<void>(resolve => document.addEventListener('DOMContentLoaded', () => resolve(), { once: true }));
+    return document;
   }
 }
 
diff --git a/typo3/sysext/core/Resources/Public/JavaScript/DocumentService.js b/typo3/sysext/core/Resources/Public/JavaScript/DocumentService.js
index 1a5be706fbe1737b446c6e6729ee48e05f8a25a1..fbcdfdec606d629eebbfd98875419203b0fd134f 100644
--- a/typo3/sysext/core/Resources/Public/JavaScript/DocumentService.js
+++ b/typo3/sysext/core/Resources/Public/JavaScript/DocumentService.js
@@ -10,4 +10,4 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-define(["require","exports"],(function(e,t){"use strict";return new class{constructor(e=window,t=document){this.windowRef=e,this.documentRef=t}ready(){return new Promise((e,t)=>{if("complete"===this.documentRef.readyState)e(this.documentRef);else{const n=setTimeout(()=>{o(),t(this.documentRef)},3e4),o=()=>{this.windowRef.removeEventListener("load",i),this.documentRef.removeEventListener("DOMContentLoaded",i)},i=()=>{o(),clearTimeout(n),e(this.documentRef)};this.windowRef.addEventListener("load",i),this.documentRef.addEventListener("DOMContentLoaded",i)}})}}}));
\ No newline at end of file
+define(["require","exports"],(function(e,t){"use strict";return new class{constructor(){this.promise=null}ready(){var e;return null!==(e=this.promise)&&void 0!==e?e:this.promise=this.createPromise()}async createPromise(){return"loading"!==document.readyState||await new Promise(e=>document.addEventListener("DOMContentLoaded",()=>e(),{once:!0})),document}}}));
\ No newline at end of file