2009-09-26 8 views

risposta

2

Creare un processo in background e restituire l'ID processo in background in modo che l'utente possa verificarlo in seguito tramite un URL segreto.

16

La direttiva ignore_user_abort e la funzione ignore_user_abort sono probabilmente ciò che si sta cercando: dovrebbe consentire di inviare la risposta al browser e, successivamente, eseguire comunque alcuni calcoli sul server.

Questo articolo potrebbe interessarti: Come utilizzare ignore_user_abort() per eseguire l'elaborazione fuori banda; citando:
EDIT 2010-03-22: rimosso il link (stava indicando http:// ! waynepan.com/2007/10/11/ ! how-to-use-ignore_user_abort-to-do-process-out-of-band/ - rimuovere gli spazi e ! se volete provare), dopo aver visto il commento di @ Joel.

In sostanza, quando si utilizza ignore_user_abort(true) in php script, lo script continuerà in esecuzione anche se l'utente preme il esc o fermarsi sul suo browser. Come lo usi ?
Un uso sarebbe quello di restituire il contenuto all'utente e consentire la connessione da chiudere mentre l'elaborazione di cose che non richiedono l'interazione utente utente.

Il seguente esempio invia $response all'utente, chiudendo la connessione (rendendo filatore/caricamento barra di arresto del browser), e quindi esegue do_function_that_takes_five_mins();

E l'esempio fornito:

ignore_user_abort(true); 
header("Connection: close"); 
header("Content-Length: " . mb_strlen($response)); 
echo $response; 
flush(); 
do_function_that_takes_five_mins(); 

(C'è dell'altro non è stato copia-incolla)


Nota che lo script PHP deve ancora adattarsi alle max_execution_time e memory_limit vincoli - il che significa che non si deve usare questo per manipolazioni che prendono troppo tempo.

Questo userà anche un processo Apache - il che significa che non dovresti avere dozzine di pagine che lo fanno allo stesso tempo.

Eppure, bel trucco per migliorare l'esperienza uso, suppongo ;-)

+0

Non funziona. Puoi provare a vederlo: ignore_user_abort (true); intestazione ('Content-Type: text/plain'); intestazione ("Connessione: chiusa"); echo 'qualcosa'; sleep (20); exit(); Ci vogliono ancora 20 secondi per rispondere. – Mask

+0

Il collegamento a "Come utilizzare ignore_user_abort() per eseguire l'elaborazione fuori banda" contiene malware (se visualizzato tramite un referente, succhia come SO). Sembra che il proprietario del blog sia stato violato ... –

+0

@Joel: grazie per il commento; Ho modificato la mia risposta per rimuovere il collegamento ;; Ho appena lasciato l'URL, senza un collegamento ipertestuale, e con un avviso –

-1

è necessario l'invito flush() per avere la risposta inviata al browser immediatamente.

2

Una specie di dipende da cosa si sta tentando di realizzare.

Nel mio caso, avevo bisogno di fare un po 'di elaborazione sul lato server, con solo una minima quantità di dati inviati al browser - informazioni di riepilogo davvero.

Stavo cercando di creare un mittente del messaggio - invia un'e-mail a oltre 250 persone, ma probabilmente molte di più (dipende da quanti si sono registrati con il sistema).

il gestore di posta PHP è veloce, ma per grandi numeri, non abbastanza veloce, quindi era destinato a scadere. Per ovviare a questo, avevo bisogno di ritardare il timeout sul lato server/PHP e tenere il browser sospeso fino a quando tutti i dati sono stati riepilogati e visualizzati.

La mia soluzione: un teaser.

essenzialmente, ho dato all'utente un messaggio indicando alcune statistiche iniziali (tentando di inviare molte e-mail), creato 2 caselle DIV (una per informazioni sullo stato corrente, la seconda per informazioni di riepilogo finali), visualizzato il piè di pagina, avviato l'elaborazione, e al termine, ha aggiornato le informazioni di riepilogo. è il seguente:

Inizia raccogliendo i dati che elaborerai e ottieni informazioni di riepilogo. Nel mio caso, ho tirato la lista degli indirizzi email, li ho convalidati e li ho contati.

quindi visualizzare l' "tentare" info:

echo "Message contents:"; 
echo "<blockquote>$msgsubject<p>$msgbody</blockquote><p>&nbsp;</p>"; 
echo "Attempting <strong>" . $num_rows . "</strong> email addresses."; 

Creare ora alcuni DIV per stato/informazione finale:

<div id=content name=content> 
<div id=progress name=progress style='border: black 1px solid; width: ".$boxwidth."px; height: 20px;'></div> 
<br> 
</div> 

dove $ boxwidth è la larghezza desideri che i tuoi barra di avanzamento per essere (spiegato più avanti)

Si noti che sono essenzialmente vuoti - li riempiremo in un secondo momento.

Infine, compila il resto della pagina visualizzando il piè di pagina della pagina (nel mio caso ho appena "incluso" il file appropriato).

Ora, tutto ciò che è ancora sospeso nel buffer di pagina, sul server (se il buffering di PHP) o sul browser (perché non è stato ancora detto che abbiamo finito), quindi proviamo a farlo avere spinto e/o visualizzati utilizzando il "ignora" e "a filo" dall'alto:

ignore_user_abort(true); 
flush(); 

Ora che il browser sta cominciando a visualizzare cose, abbiamo bisogno di dare all'utente qualcosa da vedere, quindi ecco la presa in giro - creeremo una barra di stato che mostreremo nel DIV interno e un messaggio finale per il DIV esterno.

Quindi, come si ciclo tra i dati, periodicamente (lascio "quante volte" a voi per capire), in uscita il seguente:

set_time_limit (3); 
... 
(process your data here) 
... 
<script>document.getElementById('progress').innerHTML += "<img src='images/progress_red.gif' width: $width height=20 border=0>"</script> 
flush(); 

Ciò essenzialmente impilare fino il piccolo 4x20 progress_red le immagini una accanto all'altra, facendo apparire che una barra rossa si muova sullo schermo. Nel mio caso, l'ho fatto 100 volte, in base a una percentuale del numero che stavo elaborando al momento del numero totale da elaborare. "Set_time_limit" aggiungerà 3 secondi al limite esistente, in modo che tu sappia che il tuo script non verrà eseguito nella parete del limite di tempo di PHP. Regola i 3 secondi della tua applicazione secondo necessità.

anche se la pagina è tecnicamente "completa", il codice javascript aggiornerà il DIV html e la nostra barra di avanzamento si "sposterà".

quando tutto fatto, ho poi riferire su quanti elementi sono stati effettivamente trasformati e aggiungo che al DIV HTML esterno e la pagina è completa:

<script>document.getElementById('content').innerHTML += "Message was sent to $sentcnt people."</script> 

Il browser è felice perché ha avuto tutte le sue qualifiche incontrato (alla fine della pagina sintatticamente), l'utente vede accadere qualcosa fino alla fine, e il server

Io tendo a non usare Javascript se posso aiutarlo, ma nel caso, non c'era niente di stravagante materiale CSS attraverso il Javascript, quindi è abbastanza semplice e facile vedere cosa sta succedendo e basso sovraccarico sul sito del browser. E funziona abbastanza bene.

Non ritengo che questo sia perfetto, ma per una soluzione semplice, a basso sovraccarico, funziona per me senza dover creare cronjob, meccanismi di accodamento aggiuntivi o processi secondari.

Problemi correlati