waitForNetworkIdle method

Future<bool> waitForNetworkIdle({
  1. int timeoutMillis = 30000,
  2. int idleTimeMs = 500,
})

Waits for the network to be idle

Implementation

Future<bool> waitForNetworkIdle({
  int timeoutMillis = 30000,
  int idleTimeMs = 500,
}) async {
  _checkDisposed();

  if (_controller == null) {
    throw ScrapingException.validation(
      'Browser not initialized',
      isRetryable: false,
    );
  }

  try {
    // Inject a script to track network requests
    await _controller!.evaluateJavascript(
      source: """
      window._networkRequests = 0;
      window._originalFetch = window.fetch;
      window._originalXHR = window.XMLHttpRequest.prototype.open;

      window.fetch = function() {
        window._networkRequests++;
        return window._originalFetch.apply(this, arguments).finally(() => {
          window._networkRequests--;
        });
      };

      window.XMLHttpRequest.prototype.open = function() {
        window._networkRequests++;
        this.addEventListener('loadend', () => {
          window._networkRequests--;
        });
        return window._originalXHR.apply(this, arguments);
      };
    """,
    );

    // Wait for network to be idle
    final startTime = DateTime.now();
    while (DateTime.now().difference(startTime).inMilliseconds <
        timeoutMillis) {
      final requests = await _controller!.evaluateJavascript(
        source: "window._networkRequests",
      );

      if (requests is int && requests == 0) {
        // Wait for the idle time to make sure no new requests start
        await Future.delayed(Duration(milliseconds: idleTimeMs));

        // Check again
        final requestsAfterIdle = await _controller!.evaluateJavascript(
          source: "window._networkRequests",
        );
        if (requestsAfterIdle is int && requestsAfterIdle == 0) {
          return true;
        }
      }

      await Future.delayed(const Duration(milliseconds: 100));
    }

    // Timeout reached
    return false;
  } catch (e) {
    _log('Error waiting for network idle: $e', isError: true);
    return false;
  }
}