2010-11-20 7 views
5

Sto cercando di trovare un modo per ottenere se il browser è attualmente occupato da JavaScript. Sto cercando di fare un'estensione per Firefox per iniettare un valore booleano o qualcosa del genere se la pagina corrente sta caricando qualcosa (tramite ajax o solo normali carichi di pagina), o lo stesso con uno script Greasemonkey, o attraverso qualche API JavaScript (questo sarebbe essere la soluzione migliore, ma da quello che posso vedere, nulla del genere esiste).Ottieni se il browser è occupato

Mi chiedevo quale sarebbe stato il modo migliore per farlo. Ho cercato tutorial Addon/Greasemonkey per fare qualcosa di simile a questo e non trovo nulla. Qualcuno ha qualche consiglio o risorsa che potrebbe indicarmi o soluzioni migliori per risolvere questo?

Grazie

Modifica: e per occupato, per lo più solo bisogno di sapere se il browser invia o riceve dati da un server.

risposta

2

Ecco cosa penso che finirò per fare. Questa soluzione è simile a quella di Alex ha suggerito con gli eventi jQuery, tranne che funziona con qualsiasi cosa che utilizza il XMLHttpRequest (Compresi Jquery):

var runningAjaxCount = 0; 

var oldSend = XMLHttpRequest.prototype.send; 
XMLHttpRequest.prototype.send = function() { 
    oldOnReady = this.onreadystatechange; 
    this.onreadystatechange = function() { 
     oldOnReady.call(this); 
     if(this.readyState == XMLHttpRequest.DONE) { 
      ajaxStopped(); 
     } 
    } 
    ajaxStarted(); 
    oldSend.apply(this, arguments); 
} 

function ajaxStarted() { 
    runningAjaxCount++; 
} 

function ajaxStopped() { 
    runningAjaxCount--; 
} 

function isCallingAjax() { 
    return runningAjaxCount > 0; 
} 

function isBrowserBusy() { 
    return document.readyState != "complete" && isCallingAjax(); 
} 
+0

Ho pensato di commentare e dire che 3 anni dopo, stiamo ancora utilizzando questo approccio di base e funziona benissimo! – Joel

+0

Questo è davvero fantastico! Grazie! Davvero utile per alcuni test automatici/scraping di siti web. – Evers

4

jQuery, un grande quadro javascript per la manipolazione DOM e chiamate ajax performanti, prevede due grandi ganci per determinare quando chiamate ajax sono in corso:

$.ajaxStart() e $.ajaxStop()

Entrambi questi ganci prendere una funzione di gestione che verrà chiamato quando una chiamata ajax sta per iniziare e quando tutte le chiamate ajax sono cessate, rispettivamente. Queste funzioni possono essere associate a qualsiasi elemento della pagina. È possibile impostare un valore booleano globale nel gestore $.ajaxStart() su true e reimpostarlo su falso nel gestore $.ajaxStop().

È quindi possibile controllare il flag booleano e determinare se le chiamate ajax sono in corso.

Qualcosa in questo senso:

$(document).ajaxStart(function() { 
    window.ajaxBusy = true; 
}); 

$(document).ajaxStop(function() { 
    window.ajaxBusy = false; 
}); 

Per quanto riguarda la determinazione quando il browser sta caricando la pagina corrente, si potrebbe verificare document.readyState. Restituisce una stringa di "loading" durante il caricamento del documento e una stringa di "complete" dopo il caricamento. È possibile associare un gestore a document.onreadystatechange e impostare un valore booleano globale che indicherà se il documento è ancora in fase di caricamento o meno.

Qualcosa di simile a questo:

document.onreadystatechange = function() { 
    switch (document.readyState) { 
     case "loading": 
      window.documentLoading = true; 
      break; 
     case "complete": 
      window.documentLoading = false; 
      break; 
     default: 
      window.documentLoading = false; 
    } 
} 

EDIT:

Sembra che $.ajaxStart() e $.ajaxStop() non lavoro per le chiamate ajax invocato senza jQuery. Tutti gli oggetti XMLhttprequest hanno un evento chiamato readystatechange a cui è possibile allegare un gestore. È possibile utilizzare questa funzionalità per determinare se è stata effettuata o meno una singola chiamata. È possibile trasferire tutti i riferimenti a chiamate in sospeso su un array e in un setInterval() controllare la lunghezza dell'array. Se è> 1, ci sono chiamate in piedi ajax. È un approccio approssimativo, e solo un modo per farcela. Ci sono probabilmente altri modi per farlo. Ma ecco l'approccio generale:

// declare array to hold references to outstanding requets 
window.orequets = []; 

var req = XMLHttpRequest(); 
// open the request and send it here.... 
// then attach a handler to `onreadystatechange` 
req.onreadystatechange = function() { 
    if (req.readyState != 4 || req.readyState != 3) { 
     // req is still in progress 
     orequests.push(req); 
     window.reqPos = orequests.length -1 
    } else { 
     window.orequests = orequests.slice(reqPos, reqPos + 1); 
    } 
} 

fare quanto sopra per ogni XMLHttpRequest() vi sarà l'invio, ovviamente cambiando il nome di richiesta per ciascuno di essi. Quindi eseguire un setInterval() che esegue ogni x quantità di millisecondi e controlla la proprietà length di orequests. Se è uguale a zero, non si verificano richieste, se è maggiore di zero, le richieste continuano a verificarsi.Se non si verificano richieste, è possibile cancellare l'intervallo tramite clearInterval() o mantenerlo in esecuzione.

tuo setInterval potrebbe essere simile a questo:

var ajaxInterval = setInterval(function() { 
    if (orequests.length > 0) { 
     // ajax calls are in progress 
     window.xttpBusy = true; 
    } else { 
     // ajax calls have ceased 
     window.xttpBusy = false; 
     // you could call clearInterval(ajaxInterval) here but I don't know if that's your intention 
    }, 
    3000 // run every 3 seconds. (You can decide how often you want to run it) 
}); 
+0

Il PO ha chiesto come fare questo da un estensione per Firefox, non da un web pagina che utilizza jQuery. – PleaseStand

+1

Ho letto i documenti jquery su questi due metodi e hanno cercato di individuare quello che stavo cercando. Ho ancora una domanda però: quegli eventi si legheranno solo alle chiamate di Jquery Ajax? O a qualsiasi chiamata Ajax di JavaScript? – Joel

+0

@idealmachine, stavo davvero chiedendo qualsiasi soluzione che includesse le librerie di Firefox o JavaScript. – Joel

0

Il browser tecnicamente non è mai "occupato". Il business è un termine molto soggettivo. Supponiamo che il thread principale stia eseguendo un semplice ciclo while che blocca l'esecuzione. Questo potrebbe essere considerato occupato, ma cosa succede se si ha qualcosa di simile:

function busy() {setTimeout(busy, 0);do_something();} 
busy(); 

Il browser non è stato bloccato (per se), quindi se la pagina è "occupato" è molto chiaro. Inoltre, questo non inizia nemmeno a toccare i web worker e il codice nel chrome.

Avrai difficoltà a farlo, e anche se lo fai, probabilmente non funzionerà come te lo aspetti. Buona fortuna, comunque.

+0

Intendo davvero rete occupata. Devo sapere se il browser sta inviando o registrando i dati. Aggiornerò il mio post per chiarire Grazie. – Joel