2013-06-21 13 views
8

Situazione:
Sto usando un POST $ .ajax() per inviare una richiesta a uno script php che inserisce circa 400.000-500.000 linee in un db. Questo richiede costantemente circa 3,5 - 4 minuti. (Durante questo periodo, la richiesta è IN ATTESA).

Problema:
ho bisogno di un modo per mostrare i progressi sulla pagina. (come un %). Ho provato ad usare un $ .ajax() in un setInterval che controlla ogni 5 secondi circa, ma sembra che si accumulino e si verificano tutti quando il primo (più lungo) $ .ajax() è finito.

Domanda:
Non è $ .ajax() asincrono per impostazione predefinita? Questo non dovrebbe significare che le richieste possono essere inviate in qualsiasi ordine e in qualsiasi momento, e le risposte dovrebbero essere ricevute in qualsiasi ordine e in qualsiasi momento ?? Questo ha qualcosa a che fare con async? C'è un modo per inviare periodicamente 'semi-risposte' da una richiesta? Oppure non posso inviare e ricevere richieste/risposte mentre c'è una richiesta/risposta in sospeso? (vedi il disegno fantastico qui sotto)

Grazie in anticipo !!!

multiple requests http://kshaneb.com/reqres.png

+2

+1 per il grafico. :) Hai preso in considerazione il chunking dei tuoi dati, ovvero invio di requet separati ogni 10k righe? –

+1

+1 per spiegazione. hai provato con vero asincrono .. – sathish

+0

Sono d'accordo con Zsolt sopra, Considera di dividere i tuoi dati in una richiesta più piccola che può darti una risposta più veloce, inoltre puoi calcolare% base di nessuna delle richieste completate. Anche il caricamento di dati di grandi dimensioni in una singola richiesta, anche se asincrona, si tradurrà in prestazioni più lente. –

risposta

1

Invece di fare un posto ajax è possibile inviare ad un iframe e hanno php generare l'output incrementale e inviarlo con il comando flush.

// send a hash mark for every 1000 inserts 
$a = 0; 
while ($rec = getDataForNextInsert()){ 
     $a++; 
     // do insert 
     if ($a%1000 == 0) { echo '#'; flush(); } 
} 

Sarebbe anche allora possibile interrogare il contenuto del iframe per fornire una bella visualizzazione per l'utente finale.

2

Spero che questo aiuti

$(function() 
    { 
     var statusElement = $("#status"); 

     // this function will run each 1000 ms until stopped with clearInterval() 
     var i = setInterval(function() 
     { 
      $.ajax(
      { 
       success: function (json) 
       { 
        // progress from 1-100 
        statusElement.text(json.progress + "%"); 

        // when the worker process is done (reached 100%), stop execution 
        if (json.progress == 100) clearInterval(i); 
       }, 

       error: function() 
       { 
        // on error, stop execution 
        clearInterval(i); 
       } 
      }); 
     }, 1000); 
    }); 
+0

La tua chiamata AJAX non contiene URL. Forse dovrebbe. –

7

tua lunga durata ajax-call probabilmente si apre una sessione sul server, in modo tutti i prossimi richieste sono bloccate a causa di un blocco di file di sessione.

Problema: PHP scrive i suoi dati di sessione in un file di default. Quando viene fatta una richiesta ad uno script PHP che avvia la sessione (session_start()), questo file di sessione è bloccato. Ciò significa che se la tua pagina web fa numerose richieste agli script PHP, ad esempio per caricare contenuti tramite Ajax, ciascuna richiesta potrebbe bloccare la sessione e impedire il completamento delle altre richieste. Le altre richieste si bloccheranno su session_start() fino a quando il file di sessione non verrà sbloccato. Questo è particolarmente grave se una delle tue richieste Ajax è relativamente lunga.

Soluzione: Il file di sessione rimane bloccato fino al completamento dello script o alla chiusura manuale della sessione. Per impedire il blocco di più richieste PHP (che richiedono dati $ _SESSION), è possibile avviare la sessione e chiudere la sessione. Questo sbloccherà il file di sessione e permetterà alle richieste rimanenti di continuare a funzionare, anche prima che la richiesta iniziale sia completata.

Maggiori informazioni qui: http://konrness.com/php5/how-to-prevent-blocking-php-requests/

+2

[Sarebbe preferibile] (http://meta.stackexchange.com/q/8259) includere qui le parti essenziali della risposta (non solo la causa, ma anche la soluzione) e fornire il link per riferimento. –

+0

Grazie @optimistiks. Come suggerito in questo articolo, sto usando session_write_close() prima di eseguire la parte che richiede molto tempo del mio script php e ... Funziona! Bene su localhost comunque. Sono sicuro che quando trasmetterò tutto al server ci saranno nuovi problemi. Grazie ancora! – ksb86

1

Spero che questo sarà utile per voi

Prima di tutto, è necessario disabilitare buffer di uscita nello script PHP

@apache_setenv('no-gzip', 1); 
@ini_set('zlib.output_compression', 0); 
@ini_set('implicit_flush', 1); 
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); } 
ob_implicit_flush(1); 

Poi devi seguire i tuoi progressi da PHP durante il processo, qualcosa del genere:

for($i=0;$i < 20;$i++){ 
    echo ($i > 0 ? "#":"").($i/20*100); 
    sleep(1); 
} 

Quindi, in javascript è necessario ascoltare l'evento di modifica xhr readystate e quando ciò accade, basta analizzare il testo della risposta e mostrare l'avanzamento come si desidera.

ascolto per evento:

$.ajaxPrefilter(function(options, _, jqXHR) { 
       if (options.onreadystatechange) { 
        var xhrFactory = options.xhr; 
        options.xhr = function() { 
         var xhr = xhrFactory.apply(this, arguments); 
         function handler() { 
          options.onreadystatechange(xhr, jqXHR); 
         } 
         if (xhr.addEventListener) { 
          xhr.addEventListener("readystatechange", handler, false); 
         } else { 
          setTimeout(function() { 
           var internal = xhr.onreadystatechange; 
           if (internal) { 
            xhr.onreadystatechange = function() { 
             handler(); 
             internal.apply(this, arguments); 
            }; 
           } 
          }, 0); 
         } 
         return xhr; 
        }; 
       } 
      }); 

e campione di richiesta AJAX:

$.ajax({ 
        url: "test.php", 
        cache: false, 
        onreadystatechange: function(xhr) { 
         res = xhr.responseText.split("#"); 
         $("#id").html(res[res.length-1] + "% done<br/>"); 
        }     
       }).done(function(data) { 
         $("#id").append("all done!</br>"); 
        }); 
      }); 

testato con jQuery 1.5 +

+0

mi ha aiutato, grazie. conosci qualche problema sulla compatibilità dei crossbrowser con questi codici? – littlealien

Problemi correlati