Barre de progression avec PHP & Ajax
Je suis en train de travailler sur la barre de progression qui met à jour les progrès réalisés à l'aide de requêtes ajax et les variables de session. Quand mon programme effectue de temps de fonctionnement telles que l'envoi de nombreux e-mails, etc. il vient de régler correctement les variable de session (qui contient la valeur de progression). Cette opération est lancée par la fonction post() dans le code ci-dessous.
Dans l'intervalle, la seconde fonction de demande() est exécutée en boucle tous les 500ms. Il doit retourner les progrès en cours en temps réel. Et là est le problème: chaque demande envoyée par demander() sont en attente pour les demandes envoyées par la poste() la fonction est terminée. Le plus drôle, c'est que si j'ai mis une URL comme google.com au lieu de l'url/de/de progrès, il fonctionne très bien, sauf que c'est pas ce que je veux :). Ce qui signifie que le problème est sur le côté serveur.
Ne sais pas si c'est important mais j'utilise Yii Framework.
Tout le code ci-dessous n'est rien (mais de travail) et son seul but est de montrer ce que je voulais dire.
Merci d'avance.
Désolé pour mon mauvais anglais 🙂
Vue:
<script type="text/javascript">
function ask() {
var d = new Date();
var time = d.getTime();
$.ajax({
type: 'get',
url: '/url/to/progress' + '?time=' + time,
success: function(data) {
$("#progress").html(data);
}
})
}
function post() {
var d = new Date();
var time = d.getTime();
$.ajax({
type: 'post',
url: '/url/to/post' + '?time=' + time,
data: {"some": "data"},
success: function(data) {alert(data)}
});
}
$("#test").click(
function() {
post();
var progress = setInterval("ask();", 500);
}
);
</script>
Contrôleur partie:
public function actionPost($time) {
sleep(5); //time consuming operation
echo $time . ' : ' . microtime();
exit;
}
public function actionProgress($time) {
echo $time . ' : ' . microtime();
exit;
}
OriginalL'auteur pawelo | 2012-02-16
Vous devez vous connecter pour publier un commentaire.
Je pense que votre problème ici est en rapport.
Si un script a une session ouverte, il a un verrou sur le fichier de session. Cela signifie que toutes les requêtes suivantes qui utilisent le même IDENTIFIANT de session seront en file d'attente jusqu'à ce que le premier script a libéré du verrou sur le fichier de session. Vous pouvez forcer cette avec
session_write_close()
- mais ce ne sera pas vraiment vous aider, que vous essayez de partager les progrès d'info avec le fichier de session afinpost
script aurait besoin de conserver les données de la session ouverte et accessible en écriture.Vous devrez trouver un autre moyen de partage des données entre les
post
etprogress
scripts - sipost
a les données de la session ouverte tout au long de l'exécution,progress
ne sera jamais en mesure d'accéder à la session de données jusqu'à ce que aprèspost
a fini de s'exécuter. Peut-être que vous pourriez utiliser l'ID de session pour créer un fichier temporaire quipost
a accès en écriture, dans lequel vous mettez l'indicateur de progression de données. Leprogress
pouvez vérifier le fichier et renvoyer les données. Il existe de nombreuses options pour les IPC (inter-process communication) - ce n'est pas particulièrement belle, mais elle a l'avantage de la portabilité maximale.Comme une note de côté - merci de ne pas passer des chaînes de
setInterval()
, pass fonctions. Si votre ligne devrait en fait lire:Mais serait - il préférable d'utiliser
setTimeout()
dans lesuccess
/error
gestionnaires de laask()
ajax fonction. C'est parce qu'en utilisantsetInterval()
, une nouvelle demande sera lancé indépendamment de l'état de la précédente. Il serait plus efficace d'attendre jusqu'à ce que la demande précédente a terminé avant de lancer le suivant. Donc, je voudrais faire quelque chose de plus comme ceci:...même si ce n'est toujours pas résolu la session problème.
Méfiez-vous de l'ouverture et de la fermeture de la session de données plusieurs fois dans le même script, j'ai vu des gens se plaignent qu'il ne fonctionne pas de manière fiable, donc assurez-vous de bien tester tout ce que vous venez avec.
Hmmm, peut-être que la meilleure solution est de stocker de l'avancement variable en Db ou d'un fichier. Je dois vérifier, merci!
OriginalL'auteur DaveRandom
@DaveRandom ci-dessus correctement les points que vous êtes victime d'un stockage de session de verrouillage.
La solution est assez simple. Vous voulez faire le script qui traite
post()
libérer le verrou sur les données de la session afin que le script qui gèreask()
pouvez accéder à ces données de session. Vous pouvez le faire avecsession_write_close
.L'amende imprimer ici est qu'après l'appel de
session_write_close
vous n'aurez pas accès aux variables de session, si vous avez besoin de la structure du script pourpost
en conséquence:$_SESSION
et enregistrer une copie de celui-ci.session_write_close
pour libérer la session de verrouillage.$_SESSION
directement.Alternativement, vous pouvez activer /désactiver le verrouillage de la session, plusieurs fois pendant le script de la vie:
Cette entente fait en sorte que tout le script de dormir, d'autres scripts peuvent accéder à la session de données sans problèmes.
session_write_close()
dans lepost
script" jusqu'à ce que je re-lisez la question et se rendit compte que ce qu'il essaie de faire est de partager l'avancement de l'opération longue via les données de la session. Qui, de toute évidence, vous ne pouvez pas le faire. Vous pourriez essayer etsession_write_close()
et par la suitesession_start()
lorsque vous avez besoin de mettre à jour les informations de progression - je n'ai jamais essayé moi-même mais je me rappelle avoir vu une question ici au cas où quelqu'un a été de trouver cela n'a pas fonctionné, donc si elle fonctionne partout où il a probablement l'habitude de travailler partout. DoncYou will need to come up with another way of sharing data
OriginalL'auteur Jon