it-swarm.dev

Ottenere aggiornamenti sui progressi (tramite AJAX) su un'azione del controller senza bloccare

Ho un controller con un'azione che accetta richieste su AJAX, esegue alcune manipolazioni dei dati e restituisce alcuni dati:

function publicDirectoryAjaxSearch(){
    // Check the form token
    JSession::checkToken('get') or die('Invalid Token');

    // Don't show PHP errors in raw output
    ini_set('display_errors', 'Off');

    // Sort out the session status
    $session = JFactory::getSession();
    $session->set('getOrganisationsStatus', 'Searching...');

    // Get orgs
    $response = $this->doPublicDirectorySearch();

    // Get the document object.
    $document = JFactory::getDocument();

    // Set the MIME type for JSON output.
    $document->setMimeEncoding('application/json');

    // Change the suggested filename.
    JResponse::setHeader('Content-Disposition','attachment;filename="result.json"');

    echo json_encode($response);
}

Questo metodo può richiedere del tempo, quindi sto usando JSession per memorizzare una variabile di stato getOrganisationStatus che può essere controllata periodicamente tramite AJAX per vedere fino a che punto $this->doPublicDirectorySearch() metodo ha ottenuto ...

function doPublicDirectorySearch(){
    ...
    while($running)
         $session->set('getOrganisationsStatus', 'Fetched '.$handled."/".$totalResults." results.");
    ...
}

Tuttavia, sto riscontrando alcuni problemi. Se imposto il gestore della sessione di configurazione globale di Joomla su Database la variabile di sessione getOrganisationsStatus sembra sempre "ritardare" 1 richiesta di dati dietro. Ad esempio (in preparazione per questo esempio ho cancellato tutte le sessioni esistenti):

  1. Invia una richiesta di dati tramite AJAX a publicDirectoryAjaxSearch
  2. Impostare un intervallo per ottenere la variabile della sessione di stato della richiesta su AJAX a publicDirectorySearchStatus
  3. Richiesta dati ancora in esecuzione. Il valore della sessione cambia quando $this->doPublicDirectorySearch() funziona attraverso i dati
  4. Chiamata di stato effettuata da setInterval a publicDirectorySearchStatus. La variabile di sessione restituita è vuota (questo passaggio si ripete nell'intervallo)
  5. publicDirectoryAjaxSearch richiesta dati completata. Il metodo restituisce l'oggetto JSON
  6. Chiamata di stato finale effettuata su AJAX da setInterval a publicDirectorySearchStatus. I dati restituiti (la variabile di sessione) ora mostrano il testo corretto impostato nel metodo di richiesta dati.

Se imposto la configurazione globale di Joomla per utilizzare Nessuno come gestore della sessione (ovvero il gestore basato su file incorporato in PHP), i blocchi di script (come - PHP blocca il file di sessione quando uno script accede ad esso, quindi la AJAX per scoprire lo stato deve attendere fino al termine del metodo di aggiornamento della variabile di sessione - sconfiggendo un po 'il punto ).

Dove sto sbagliando? Come posso..

  1. Effettua una chiamata per ottenere dati (richiede del tempo)
  2. Effettuare una chiamata separata per ottenere una variabile di sessione che è stata manipolata nel tempo dalla prima chiamata
2
codinghands

Tutte le richieste della tua pagina condividono la stessa sessione utente. Pertanto, se chiamate più pagine, in modo asincrono, nella stessa sessione, è possibile trovare una condizione di gara . http://en.wikipedia.org/wiki/Race_condition

Poiché PHP non è multithreading, non esistono meccanismi di blocco per evitare questi casi.

La soluzione migliore è evitare la condizione: riorganizzare il circuito principale e spostare il controllo sul lato Ajax. In questo modo, il browser chiama un'inizializzazione , il ciclo interno come molte volte se necessario e la finalizzazione .

  • Hai il controllo in modo da poter mostrare lo stato di avanzamento
  • Se hai migliaia di articoli da elaborare, puoi definire lotti discreti di articoli da elaborare (anziché uno per uno)
2
Anibal