2010-12-16 199 views
5

Je cherche à faire une longue interrogation pour "pousser" des données vers le client et je fais également d'autres appels AJAX sans rapport avec le serveur en parallèle avec la longue interrogation. Il semble que mes autres appels AJAX ne se termineront pas tant que le sondage long n'aura pas reçu de réponse (réponse ou expiration). Lorsque je parcours le Javascript, il apparaît que la deuxième requête AJAX est envoyée au bon moment, mais la réponse n'est pas reçue tant que la demande d'interrogation longue n'a pas reçu de réponse. Une idée de ce qui se passe?Interrogation longue verrouillant d'autres appels AJAX

Voici le code pour la partie longue de vote:

côté serveur:

function getPlaylistTracksIfChanged($playlist_id, $numClientTracks) { 
    $reportChange = false; 
    for($i = 0; $i < 10; $i++) { 
    $numServerTracks = $this->PlaylistTrack->find('count', array(
    'conditions' => array('playlist_id' => $playlist_id) 
    ) 
    ); 

    if($numClientTracks != $numServerTracks) { 
    $reportChange = true; 
    break; 

    } 

    sleep(3); 

    } 

    if($reportChange) { 
    $playlist_tracks = $this->PlaylistTrack->find('all', array(
    'conditions' => array('playlist_id' => $playlist_id), 
    'order' => array('PlaylistTrack.position') 
    ) 
    ); 

    $this->set('playlist_tracks', $playlist_tracks); 
    $this->layout = false; 
    $this->render('show_playlist_tracks_list'); 

    } else { 
    $this->autoRender = false; 
    return 'false'; 
    } 

} 

côté client:

function checkForChangesOnServer() { 
$.post('/getResultsIfChanged/' + playlist_id + '/' + $('#sortable_tracks').children().size(), function(results) { 

    if(results == 'false') { 
    //alert('no change'); 
    } else { 
    //alert('change'); 
    } 

    checkForPlaylistChangesOnServer(); 

}); 
} 

Et un échantillon d'un autre appel AJAX:

Côté serveur:

function getLibraryTracksStartingWithLetter($user_id, $letter) { 
    $results = $this->Track->find(
    'all', 
    array(
    'conditions' => array(
    'user_id' => $user_id, 
    'OR' => array(
     'Track.artist LIKE' => $letter . '%', 
     'Track.name LIKE' => $letter . '%' 
    ) 
    ), 
    'order' => array('case when Track.artist = "" then 1 else 0 end', 'Track.artist', 'Track.name') 
    ) 
); 

    $this->set('results', $results); 
    $this->layout = false; 
    $this->render('show_library_results_list'); 
} 

côté client:

function loadLibraryResultsForLetter(letter) { 
highlightLetterFilter(letter); 

$.post('/getLibraryTracksStartingWithLetter/' + user_id + '/' + letter, function(results) { 
    updateLibraryResults(results); 
}); 
} 

Répondre

13

On dirait que vous avez rencontré le verrou de fichier de session.

Exécutez session_write_close() (ou la fonction correspondante dans cakephp) pour fermer la session au début du point de terminaison ajax.

+0

ne savait pas à ce sujet trucs cool – RageZ

+1

@RageZ: chaque développeur php doit prendre ce problème :-) – zerkms

+0

du sens maintenant, je pense à ce – RageZ

0

Cela se produit en raison des verrous de fichiers de session. Dans CakePHP vous pouvez choisir d'autres options pour la gestion de session. Vous pouvez enregistrer des sessions dans la base de données, dans le cache, etc. Vous n'attendez donc pas les problèmes de verrouillage de fichier.

Les configurations intégrées sont:

php - Enregistre les sessions avec les paramètres standard dans votre fichier php.ini. Cake - Enregistre les sessions en tant que fichiers dans app/tmp/sessions. C'est une bonne option sur les hôtes qui ne vous permettent pas d'écrire en dehors de votre propre répertoire personnel .

base de données - Utilisez les sessions de base de données intégrées.

cache - utilise les sessions de cache intégrées.

http://book.cakephp.org/2.0/en/development/sessions.html#built-in-session-handlers-configuration

Bien sûr, vous pouvez faire session_write_close(), mais vous devez vous assurer qu'aucun changement nécessaire en session entre deux chargements de page.

question similaires: Simultaneous Requests to PHP Script

0

il travaille pour symfony 1.4. utilisateur session_write_close(); au lieu de $this->getUser()->shutdown();