web-dev-qa-db-fra.com

Obtenir des mises à jour de progrès (via AJAX) sur une action de contrôleur sans bloquer

J'ai un contrôleur avec une action qui accepte les demandes via AJAX, effectue certaines manipulations de données et renvoie des données:

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);
}

Cette méthode peut prendre un certain temps. J'utilise donc JSession pour stocker une variable d'état getOrganisationStatus qui peut être vérifiée périodiquement via AJAX pour voir dans quelle mesure la $this->doPublicDirectorySearch() la méthode a été obtenue ...

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

Cependant, j'ai quelques problèmes. Si je règle le gestionnaire de session de configuration globale Joomla sur Base de données , la variable de session getOrganisationsStatus semble toujours "retarder" une demande de données. Par exemple (dans la préparation de cet exemple, j'ai effacé toutes les sessions existantes):

  1. Faites une demande de données via AJAX à publicDirectoryAjaxSearch
  2. Définissez un intervalle pour obtenir la variable de session de statut de requête sur AJAX à publicDirectorySearchStatus
  3. La demande de données est toujours en cours d'exécution. La valeur de session changeant comme $this->doPublicDirectorySearch() fonctionne avec les données
  4. Appel d'état passé de setInterval à publicDirectorySearchStatus. La variable de session renvoyée est vide (cette étape se répète sur l'intervalle)
  5. publicDirectoryAjaxSearch demande de données terminée. La méthode retourne un objet JSON
  6. Appel d'état final effectué AJAX de setInterval à publicDirectorySearchStatus. Les données renvoyées (la variable de session) affichent désormais le texte correct défini dans la méthode de demande de données.

Si je configure la configuration globale de Joomla pour qu'elle utilise None comme gestionnaire de session (c'est-à-dire le gestionnaire de fichiers intégré de PHP), le script se bloque (en tant que - PHP verrouille le fichier de session quand un script y accède, l'appel AJAX pour connaître le statut doit attendre que la méthode mettant à jour la variable de session se termine - vider quelque peu le point ).

Où vais-je mal? Comment puis-je..

  1. Passer un appel pour obtenir des données (prend un peu de temps)
  2. Effectuer un appel séparé pour obtenir une variable de session manipulée dans le temps par le premier appel
2
codinghands

Toutes vos demandes de page partagent la même session d'utilisateur. Ainsi, si vous appelez plusieurs pages de manière asynchrone au cours d'une même session, vous pouvez trouver une condition de concurrence . http://en.wikipedia.org/wiki/Race_condition

Comme PHP n'est pas multithreading, il n'y a pas de mécanisme de verrouillage pour éviter ces cas.

La meilleure solution consiste à éviter la condition: réorganisez la boucle principale et déplacez le contrôle du côté Ajax. De cette manière, le navigateur appelle une initialisation , la boucle interne comme plusieurs fois que nécessaire, et la finalisation .

  • Vous avez le contrôle afin que vous puissiez afficher l'état d'avancement
  • Si vous avez des milliers d'éléments à traiter, vous pouvez définir des lots distincts d'éléments à traiter (au lieu d'un à un).
2
Anibal