Bonjour à tous
Je reviens sur un sujet que j'avais abordé il y a quelque temps et que je ne retrouve plus dans le forum.
XMLHTTPRequest en mode synchrone est considéré par les Maîtres du Web comme obsolète car il empêche l'utilisateur de faire quoi que ce soit durant le chargement de l'élément désiré.
Sachant que lesdits Maitres du Web ont la capacité de décider que ce qu'ils ont considéré comme obsolète n'est plus supporté (voir les récents effets sur les plug-ins) je me suis résolu à faire quelque chose pour remplacer les chargements synchrones, non pas par des chargements asynchrones qui ne correspondent pas à mes besoins, mais par d'autres mécanismes assurant un chargement synchrone sans contrevenir aux tables de la nouvelle loi.
Pour cela, j'ai développé l'approche suivante:
1) au cours du chargement de la page, avant l'évènement "onload", je génère une nouvelle balise <script> dans le <head> de la page, sous la forme
<script type="text/javascript" src="mon_programme.php?param=mes_parametres"></script>

Ce qui provoque l'appel de mon_programme.php avant que la page soit complètement chargée, ou plus exactement la page n'est considérée comme chargée que quand cette page de script a été chargée
2) dans le traitement "onload" de la page, je fais appel à ces scripts pour compléter la page avec les informations désirées

Cela fonctionne, même si j'aurais préféré quelque chose de moins contourné.

Auriez vous d'autres mécanismes moins farfelus à proposer pour effectuer cette opération, qui consiste essentiellement à remplir une <div> ou autre balise avec du HTML généré dynamiquement, sans utiliser AJAX synchrone?

Merci de vos avis.
Modifié par PapyJP (05 Apr 2017 - 11:32)
Hello !

Je ne comprends pas vraiment quel est l'intérêt de charger dynamiquement des éléments de la page, si c'est pour le faire de manière synchrone (sans vouloir critiquer hein Smiley smile ). Est-ce que tu peux préciser les contraintes qui t'ont amenées à faire ça ?

Personnellement, je trouve que tu te compliques un peu la vie pour rien. Générer toute la page en PHP (y compris les éléments que tu génères actuellement en JS) me paraît être une solution bien plus simple, à moins que j'ai manqué un truc ...
Je comprends que tu ne comprennes pas, la situation est un peu particulière.

Ce site est géré par deux personnes, l'une (le propriétaire du site) s'occupe du contenu, l'autre (c'est à dire moi même) s'occupe des aspects techniques.

Le propriétaire du site connait suffisamment de HTML pour écrire le contenu selon des directives que je lui ai données sous forme de snippet DreamWeaver. Le reste est fait par scripts JavaScript, CSS et quelques programmes PHP dont le but est de travailler sur le contenu du site, par exemple obtenir la liste des fichiers de certains répertoires et générer des liens, en fonction des modifications apportées par le propriétaire, ou interpréter des commandes simples pour réaliser des présentations complexes.

Par exemple, pour afficher cette page, la liste des tombes des pharaons est donnée simplement sous la forme de la liste des pages à afficher.

Au chargement de la page, un script JavaScript provoque l'exécution d'un programme PHP qui retrouve les informations contenues dans les répertoires contenant ces pages, et génère la collection d'images et de textes, qui plus est dans un ordre déduit du contenu de ces fichiers, quel que soit l'ordre dans lequel l'auteur a donné la liste de ces pages.

J'avais initialement fait le script en question de telle façon qu'il génère un appel AJAX synchrone, ce qui m'a valu des messages des navigateurs comme quoi les appels synchrones étaient politiquement incorrects et obsolètes. La raison de cet "embargo" est le fait que durant le chargement l'utilisateur ne peut pas agir sur la page, ce qui n'est pas un inconvénient dans ce cas de figure précis.
Néanmoins je sais par expérience qu'entre des messages d'alerte et le refus de supporter une fonction qui tourne depuis des lustres, il n'y a que l'épaisseur d'une feuille de papier.
J'ai donc décidé de changer les choses techniquement, sans impact sur le travail effectué par le propriétaire.

Comme on peut le voir sur cet exemple, ça marche correctement, mais je trouve ce mécanisme un peu compliqué. C'est pour cela que je voudrais savoir si d'autres personnes n'auraient pas -- à tout hasard -- un mécanisme plus simple.
Modifié par PapyJP (06 Apr 2017 - 18:30)
Bonsoir,
Si c'est juste le message du navigateur qui vous tracasse, vous pouvez utiliser une petite fonction qui chaîne des appels asynchrones. A la fin de chaque requête, vous lancez la suivante.
<?php
if(isset($_GET["p"])){
  if($_GET["p"]==2){
    header('HTTP/1.0 404 Not Found'); // une des pages n'existe pas, pour test
  }else{
    sleep(1); // juste pour montrer que la requête suivante "attend" la fin de celle-ci
    echo "Contenu de la page ".$_GET["p"];
  }
  exit();
}
?><!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="utf-8">
  <title>Test ajax, voir console</title>
</head>
<body>
<script type="text/javascript">
var ajaxchain=function(urls){
  if(!urls.length) return;
  var url=urls.shift();
  console.log("Chargement de "+url)
  var xhr=new XMLHttpRequest();
  xhr.onload=function(){
    if(xhr.status!=200){
      console.log("Echec lors du chargement de "+url);
    }else{
      console.log(url+" reçue : "+xhr.response);
    }
    ajaxchain(urls);
  };
  xhr.open("GET",url,true);
  xhr.send();
};
ajaxchain(["index.php?p=1","index.php?p=2","index.php?p=3"]);
</script>
</body>
</html>

J'ai fait le choix de poursuivre l'exécution des requêtes quand une échoue (p=2 dans l'exemple), mais on peut très bien adapter (voire paramétrer) la fonction pour avoir un comportement différent.

A+
Avec du jquery il me semble que tu peux faire cela.

Si on regarde l'ajax de jquery on peut préciser async false ce qui permettrait peut être de faire ce que tu souhaite.

Mais bon je ne comprendrais jamais pourquoi utilisé un mode synchrone... malgré tes explications..
@Seventears
Merci de cette réponse
Cette approche suppose que la page n'est pas un fichier HTML mais un fichier PHP, ce que je ne tiens pas à faire pour ne pas perturber les habitudes du propriétaire du site. C'est essentiellement pour cela que je cherche un moyen d'intégrer le résultat d'un programme PHP dans une page HTML alors que le design de base consiste à faire l'inverse.
@Jencal
Merci de ta réponse.

Je crois que je vais en rester à ma solution. Je comprends que je suis dans un cas très particulier et qu'il n'y a pas beaucoup de personnes qui se posent ce genre de question, donc pas étonnant de ne pas trouver de réponse
Modifié par PapyJP (07 Apr 2017 - 11:03)
J'ai utilisé du PHP pour me faciliter l'exemple (un seul fichier à créer), mais ça fonctionne avec n'importe quel type de fichier.
Bonsoir,

ta technique est archaïque. Ca me fait penser aux livres d'or hébergés sur un service spécifique, quand les livres d'or avaient la cote, dans les années 2000.
Ils demandaient exactement à celui qui voulait inclure le livre d'or sur sa page d'ajouter un script, qui affichait le contenu à coups de document.write.

Si tu veux, tu peux encore faire plus tordu, en passant par une image, et si tu veux atteindre le comble, tu fais que cette image fasse 1px sur 1px et soit placée dans le coin en haut à gauche de l'écran ou personne n'y fera attention...

OK, j'arrête de déconner.

Je ne comprends toujours pas pourquoi tu tiens au synchronisme.

Si tu n'as qu'une seule requête à faire, alors ça ne change pas ton code tant que ça.


xhr = new XmlHttpRequest();
xhr.open('page.php', 'GET', true);
xhr.send(null);
document.getElementById('toto') .innerHTML = xhr.responseText;


versus


xhr = new XmlHttpRequest();
xhr.onload = function(){
document.getElementById('toto') .innerHTML = xhr.responseText;
};
xhr.open('page.php', 'GET', false);
xhr.send(null);


Tu vois, ça ne change pas grand chose.

ET si tu as peur que l'utilisateur entrevoie une page blanche pendant quelques instants, je ne pense pas que tu aies plus de risques en asynchrone qu'en synchrone, je dirais que c'est même le contraire.
Techniquement ça ne change rien, la requête à faire est la même, la page ne sera peut-être pas moins longtemps, mais en tout cas pas plus longtemps blanche. L'avantage c'est que tous les éléments qui sont derrière ton script et qui n'en dépendent pas pourront se charger en parralèle.

Et pour le gars qui édite les pages HTML, je ne vois pas ce que ça change...

Si tu veux être synchrone parce qu'une requête a besoin du résultat d'une requête précédente, alors quelqu'un ci-dessus te propose une idée assez simple pour les chaîner correctement.
On peut faire encore mieux avec les promesses et demain avec async/await, mais ce qu'on te propose est tout à fait valide.
Salut,

Je t'avoue que je ne comprends pas la nécessité de devoir faire toutes tes requêtes en synchrone. J'aurais répondu comme mon prédécesseur à la question.

Je me permet de soulever une autre question même si un poil hors-sujet, pour quelle raison adopter une architecture aussi particulière pour ton site ? Un gestionnaire de contenu simplifié, ça serait pas beaucoup plus simple ? Après réflexion, on dirait que tu n'utilises simplement pas de base de données, d'où le fait que le propriétaire doit créer lui même des fichiers HTML et toi de gérer tout le traitement derrière.

EDIT : J'ai check le code source et la page que tu as link, et je comprends mieux la manière dont tu gère le contenu. J'espère que tu es vraiment forcé d'utiliser cette méthode, car comme dirait QuentinC, c'est vraiment tordu. Si tu as la possibilité de changer je te le conseillerais.
Modifié par Anymah (09 Apr 2017 - 20:36)
Merci de ta réponse

Si c'était un des sites que je gère personnellement, je ne travaillerais pas du tout comme ça: il serait écrit en PHP et les pages seraient générées à partir de textes contenus dans des fichiers xml, comme je le fais pour ce site ou pour cet autre site

Dans le cas présent, je dois travailler avec d'autres contraintes.
C'est le lot de tout ingénieur: utiliser les techniques les plus appropriées au contexte dans lequel on travaille.
J'ai eu un collègue qui a été responsable de monter une usine d'aluminium en Sibérie du temps de Brejnev: il fallait s'adapter au climat, aux embargos sur certaines techno à destination de l'URSS, au fait que la seule façon d'acheminer le matériel était de remonter un fleuve pris par les glaces 5 mois de l'année...

En fait, c'est ce que je trouve de plus amusant dans ce métier! ça oblige à se tenir au courant de multiples techniques, à se remettre en permanence en question, bref à être jeune. A mon âge, cette gymnastique intellectuelle permanente est une source de jouvence bienvenue.
@Seven tears
Désolé de ne pas avoir répondu plus tôt à la solution d'enchaînement de requêtes asynchrones.
Cela correspondait à un état de mes réflexions: j'avais été perturbé par le fait que 3 requêtes asynchrones provoquaient un fort clignotement de l'écran. En les enchaînant et en traitant tout le reaffichage sur la dernière, on doit pouvoir effectivement supprimer le clignotement.
Dans ma solution actuelle, c'est beaucoup plus simple: j'utilise le fait que le chargement des fichiers "auxiliaires" (Javascript, mais également CSS) se produit de façon asynchrone et que la page n'est considérée comme "chargée" que quand tous ces fichiers ont été chargés.
En faisant quelques recherches complémentaires, j'ai vu que bien entendu je n'avais rien inventé et que d'autres personnes l'utilisent depuis longtemps.
Ok, je craignais que vous n'ayez zappé ma proposition à cause de l'utilisation (anecdotique) de PHP.

Sinon, juste pour alimenter la "polémique", je suis assez d'accord avec vous, le mode synchrone c'est bien aussi, quand on sait ce que l'on fait, par exemple un chargement de données au démarrage d'une appli web.
Le plus drôle est de voir des scripts qui créent un message d'attente à base d'overlay (et le fameux gif tournant) pour empêcher les clics (sans empêcher la navigation clavier...) lors de l'exécution de requêtes asynchrones.