Skip to content

Commit e09039e

Browse files
author
NikolayAvramov
committed
Refactor implementation of WaitForAjax
1 parent 8f1049c commit e09039e

File tree

1 file changed

+39
-44
lines changed

1 file changed

+39
-44
lines changed

bellatrix.web/src/main/java/solutions/bellatrix/web/services/BrowserService.java

Lines changed: 39 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
import java.time.Duration;
3838
import java.util.ArrayList;
3939
import java.util.List;
40-
import java.util.Objects;
41-
import java.util.concurrent.atomic.AtomicInteger;
4240
import java.util.function.Function;
4341
import java.util.logging.Level;
4442

@@ -225,56 +223,16 @@ public List<String> getRequestEntries(String partialUrl) {
225223
public void waitForAjax() {
226224
long ajaxTimeout = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getWaitForAjaxTimeout();
227225
long sleepInterval = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getSleepInterval();
228-
AtomicInteger ajaxConnections = new AtomicInteger();
229226
try {
230-
Wait.retry(() -> {
231-
var numberOfAjaxConnections = getJavascriptExecutor().executeScript("return !isNaN(window.$openHTTPs) ? window.$openHTTPs : null");
232-
if (Objects.nonNull(numberOfAjaxConnections)) {
233-
ajaxConnections.set(Integer.parseInt(numberOfAjaxConnections.toString()));
234-
if (ajaxConnections.get() > 0) {
235-
String message = "Waiting for %s Ajax Connections...".formatted(ajaxConnections);
236-
injectInfoNotificationToast(message);
237-
Log.info(message);
238-
throw new TimeoutException(message);
239-
}
240-
} else {
241-
monkeyPatchXMLHttpRequest();
242-
}
243-
},
244-
Duration.ofSeconds(ajaxTimeout),
245-
Duration.ofSeconds(sleepInterval),
246-
true,
247-
TimeoutException.class);
227+
waitForXhrIdle(Duration.ofSeconds(ajaxTimeout), Duration.ofSeconds(sleepInterval));
248228
}
249229
catch (Exception e) {
250-
var message = "Timed out waiting for %s Ajax connections.".formatted(ajaxConnections.get());
230+
var message = "Timed out waiting for Async requests. Continuing...";
251231
Log.error(message);
252232
injectErrorNotificationToast(message);
253233
}
254234
}
255235

256-
private void monkeyPatchXMLHttpRequest() {
257-
var numberOfAjaxConnections = getJavascriptExecutor().executeScript(("return !isNaN(window.$openHTTPs) ? window.$openHTTPs : null"));
258-
259-
if (Objects.isNull(numberOfAjaxConnections)) {
260-
var script = "(function() {" +
261-
"const oldOpen = XMLHttpRequest.prototype.open;" +
262-
"window.$openHTTPs = 0;" +
263-
"XMLHttpRequest.prototype.open = function() {" +
264-
"window.$openHTTPs++;" +
265-
"this.addEventListener('readystatechange', function() {" +
266-
"if(this.readyState == 4) {" +
267-
"window.$openHTTPs--;" +
268-
"}" +
269-
"}, false);" +
270-
"return oldOpen.call(this, ...arguments);" +
271-
"}" +
272-
"})();";
273-
274-
getJavascriptExecutor().executeScript(script);
275-
}
276-
}
277-
278236
public void waitForAjaxRequest(String requestPartialUrl, int additionalTimeoutInSeconds) {
279237
long ajaxTimeout = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getWaitForAjaxTimeout();
280238
long sleepInterval = ConfigurationService.get(WebSettings.class).getTimeoutSettings().getSleepInterval();
@@ -559,4 +517,41 @@ public String getLastClipboardEntry() {
559517
return "";
560518
}
561519
}
520+
521+
public void waitForXhrIdle(Duration idleGap,
522+
Duration timeout) {
523+
524+
JavascriptExecutor js = this.getJavascriptExecutor();
525+
long start = System.nanoTime();
526+
long deadline = start + timeout.toNanos();
527+
long gapMs = idleGap.toMillis();
528+
529+
while (System.nanoTime() < deadline) {
530+
try {
531+
Long active = (Long) js.executeScript(XHR_ACTIVE_JS, gapMs);
532+
if (active == 0) {
533+
logElapsed(start);
534+
return;
535+
}
536+
Thread.sleep(40);
537+
} catch (Exception e) {
538+
// ignore and retry until timeout
539+
}
540+
}
541+
logElapsed(start);
542+
// Log.error("Timed-out waiting for XHR idle");
543+
}
544+
545+
private void logElapsed(long startNano) {
546+
long ms = (System.nanoTime() - startNano) / 1_000_000;
547+
Log.info("[Browser Wait] Waited %d ms for pending XHRs %n", ms);
548+
}
549+
550+
private final String XHR_ACTIVE_JS =
551+
"const now = performance.now();" +
552+
"return performance.getEntriesByType('resource')" +
553+
" .filter(e => e.initiatorType === 'xmlhttprequest' || e.initiatorType === 'fetch')" +
554+
" .filter(e => !e.responseEnd || e.responseEnd > now - arguments[0])" + // still running
555+
" .length;";
556+
562557
}

0 commit comments

Comments
 (0)