Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.8 KiB
name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
| name | kind | lang | domain | version | purity | signature | description | tags | uses_functions | uses_types | returns | returns_optional | error_type | imports | params | output | tested | tests | test_file_path | file_path | |||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| cdp_wait_idle | function | go | browser | 1.2.0 | impure | func CdpWaitIdle(c *CDPConn, opts CdpWaitIdleOpts) error | Espera a que la actividad de red de la pagina llegue a idle usando eventos CDP Network.*. Lleva un contador de requests en vuelo (inflight) via InflightTracker: trackea por requestId, excluye conexiones persistentes (WebSocket, EventSource) que nunca terminan. Cuando inflight <= MaxInflight (default 2) de forma continuada durante QuietMs ms, retorna nil. Inmune a extensiones que mutan el DOM (Dark Reader, uBlock) y a animaciones JS. Si se alcanza Timeout sin lograr la ventana quieta, retorna error con el inflight actual. |
|
false | error_go_core |
|
|
nil si la red llega a idle dentro del timeout; error descriptivo con inflight actual si se agota el tiempo o la conexion falla | true |
|
functions/browser/cdp_wait_idle_test.go | functions/browser/cdp_wait_idle.go |
Ejemplo
conn, _ := CdpConnect(9222)
CdpNavigate(conn, "https://my-spa.com/dashboard")
// Esperar readyState=complete primero.
_ = CdpWaitLoad(conn, 30*time.Second)
// Luego esperar a que la red quede idle (sin requests en vuelo).
if err := CdpWaitIdle(conn, CdpWaitIdleOpts{
QuietMs: 500, // 500 ms sin requests en vuelo
Timeout: 8 * time.Second,
MaxInflight: 0, // 0 = idle absoluto; 1+ = tolera polling/WS
PollMs: 100,
}); err != nil {
log.Fatal("red no llego a idle:", err)
}
html, _ := CdpGetHTML(conn)
Cuando usarla
Cuando CdpWaitLoad no basta porque la SPA lanza fetch/XHR adicionales tras readyState=complete y necesitas esperar a que terminen antes de extraer HTML o hacer clicks. Usar justo despues de CdpWaitLoad o de CdpNavigate.
Preferir esta funcion sobre la version DOM-length anterior cuando la pagina tenga extensiones activas (Dark Reader, uBlock) o animaciones JS que mutan el DOM continuamente: esas fuentes de ruido no afectan el contador de red.
Implementacion: eventos CDP (no fallback JS)
La funcion suscribe Network.requestWillBeSent, Network.loadingFinished y Network.loadingFailed usando c.OnEvent, el mismo mecanismo que cdp_har_record. CDPConn soporta multiples consumidores por metodo (slice de handlers), por lo que esta funcion y cdp_har_record pueden usarse en paralelo sobre la misma conexion sin conflicto. El fallback JS (window.__fn_inflight via XHR/fetch hook) no fue necesario.
Gotchas
- MaxInflight default = 2: la web moderna mantiene 1-2 beacons/analytics de fondo que rara vez dejan inflight en 0. El zero-value de
MaxInflight(0) se reescribe a 2 para no colgar hasta el timeout. Para exigir idle absoluto en una página simple, no hay valor de "0 explícito" (0 == default); usa una página sin analytics o asume el umbral 2. - WebSocket / EventSource excluidos del conteo: estas conexiones persistentes no emiten
loadingFinished, así que contarlas dejaría inflight clavado para siempre. ElInflightTrackerlas ignora enrequestWillBeSent(porparams.type). Un stream WS/SSE abierto ya NO impide llegar a idle. - Polling/long-poll periódico: si la página lanza un XHR cada N segundos, inflight oscila; con
MaxInflight: 2(default) suele tolerarse. Si no, reduceQuietMs(ej. 200 ms) para capturar la ventana entre polls. - Error incluye inflight actual: el mensaje de timeout incluye
inflight=Npara diagnóstico. - Network.enable/disable: la función habilita Network al entrar y lo deshabilita al salir via defer. No interleave con
cdp_har_recorden la misma conexión salvo orden de cierre controlado. - Tests sin Chrome: el núcleo (
InflightTracker) se testea con secuencias de eventos sintéticas. El bucle de polling con timeout real requiere Chrome y no está simulado.
Capability growth log
- v1.2.0 (2026-06-06) — refactor a
InflightTrackerpuro (testeable sin red); default MaxInflight 0→2 (analytics ya no cuelga); excluye WebSocket/EventSource del conteo (no terminan); tracking por requestId (finish de request no contado = no-op). - v1.1.0 (2026-06-05) — cambia señal DOM-length → network-idle via eventos CDP Network.*; añade MaxInflight configurable; defaults mas ajustados (QuietMs 800→500, Timeout 15s→8s, PollMs 200→100).