IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

[Deprecation] Synchronous XMLHttpRequest


Sujet :

JavaScript

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    320
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 320
    Points : 79
    Points
    79
    Par défaut [Deprecation] Synchronous XMLHttpRequest
    Bonjour,
    Je souhaite tester si un fichier existe sur un serveur1, s'il existe, il utilise cette adresse, s'il n'existe pas il teste si le fichier existe sur un serveur2, s'il existe, il utilise l'adresse du serveur2.

    Actuellement j'ai ce code

    Code JS : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
        function fileExist(url) {
            var xhr = new XMLHttpRequest();
            xhr.open('HEAD', url, false);
            xhr.send();
            if (xhr.status == 200) {
                console.log("File exist");
                return true;
            } else if (xhr.status == 404) {
                console.log("File does not exist");
                return false;
            } else if (xhr.status !== 200 || xhr.status !== 404) {
                console.log("Error - Status: " + xhr.status);
                return false;
            }
        }
     
        function initmap() {
            [...]
                var PSEUDO1Url = "http://PSEUDO1.free.fr/DOSSIER/FICHIER.kmz";
                var PSEUDO2Url = "http://PSEUDO2.free.fr/DOSSIER/FICHIER.kmz";
     
                var kmzUrl;
                if (fileExist (PSEUDO1Url) == true) {
                    kmzUrl = PSEUDO1Url;
                } else if (fileExist (PSEUDO2Url) == true){
                     kmzUrl = PSEUDO2Url;
                } else {
                    kmzUrl = "";
                }
     
                var kmzLayer = new google.maps.KmlLayer(kmzUrl);
                kmzLayer.setMap(map);
                console.log("URL: " + kmzUrl);
            [...]
        }

    mais ça me retourne un Warning en console.

    Nom : Capture d’écran 2019-05-05 à 12.34.57.png
Affichages : 536
Taille : 19,3 Ko

    Actuellement tout ce code fonctionne parfaitement mais je me suis mis en tête de le corriger pour ne plus avoir le Warning.

    Si j'ai bien compris, le paramètre async doit être à true mais alors fileExist() me retourne un statut à 0... et mon fichier.kmz ne se charge pas.
    J'ai lu et testé beaucoup de manières différentes mais rien ne fonctionne. (c'est surement moi qui m'y prends mal ...)

    Comment vous feriez pour supprimer ce Warning ?

    Merci

  2. #2
    Expert confirmé Avatar de psychadelic
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    2 529
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 2 529
    Points : 4 749
    Points
    4 749
    Par défaut
    à priori si tu passes en mode asynchrone, alors la réponse de chaque requête est décalée et arrive forcément après x des requêtes suivantes sur les serveurs de rechanges, ce qui fait que très vite tu te retrouves avec des tas de requêtes et leurs réponses se chevauchant.
    Tu es obligé de gérer soit dans les callbacks, mais ça risque d'être un bordel, soit par les promesses

  3. #3
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Points : 6 755
    Points
    6 755
    Par défaut
    La méthode qui demande le moins de changements dans le code, à mon avis, est d’utiliser await. L’inconvénient, c’est que c’est un ajout récent du langage et il n’est pas supporté par les vieux navigateurs, notamment Internet Explorer. Au besoin, tu pourras utiliser un transpileur comme par exemple BabelJS.

    Pour te permettre d’utiliser await avec ta fonction fileExists(), tu dois la modifier pour qu’elle retourne une promesse. C’est également ce que suggérait psychadelic.
    Je t’invite à te documenter sur les promesses en consultant par exemple la page du MDN « Utiliser les promesses » quand tu auras le temps. Pour l’instant, tu as simplement besoin de savoir deux choses :
    1. fileExists() doit renvoyer une promesse ;
    2. une promesse reçoit en argument une fonction, dans laquelle se passent les choses asynchrones, et en gros on utilise resolve() à la place de return.


    Pour gérer la requête XHR en mode asynchrone, j’utilise l’évènement 'loadend'.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    function fileExist(url) {
        return new Promise((resolve, reject) => {
          const xhr = new XMLHttpRequest();
     
          xhr.addEventListener('loadend', () => {
              if (xhr.status == 200) {
                  console.log("File exist");
                  resolve(true);
              } else if (xhr.status == 404) {
                  console.log("File does not exist");
                  resolve(false);
              } else /*if (xhr.status !== 200 || xhr.status !== 404)*/ {
                  console.log("Error - Status: " + xhr.status);
                  resolve(false);
              }
          });
     
          xhr.open('HEAD', url);
          xhr.send();
        });
    }
    Au passage, attention à un petit problème de logique dans ton second else : la condition « status est différent de 200 OU différent de 404 » est vraie tout le temps, car si status est égal à 200, alors il est différent de 404 et réciproquement.
    Attention aussi au cas où status = 0, ça signifie que la requête n’est pas partie (problème de permission, le plus souvent) et donc ça ne donne pas l’information sur l’existence ou non du fichier.

    On a à présent une fonction fileExists() qui renvoie une promesse. Tout ce qu’on a à faire, c’est placer un await devant chaque appel à cette fonction. Un détail cependant : il faut « prévenir » le moteur JS que ce bout de code contient des await, en rendant explicitement asynchrone la fonction qui se trouve autour. On fait ça en ajoutant le marqueur async à la fonction initmap().

    Voici ce que ça donne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    async function initmap() {
        [...]
            var PSEUDO1Url = "http://PSEUDO1.free.fr/DOSSIER/FICHIER.kmz";
            var PSEUDO2Url = "http://PSEUDO2.free.fr/DOSSIER/FICHIER.kmz";
     
            var kmzUrl;
            if (await fileExist (PSEUDO1Url) == true) {
                kmzUrl = PSEUDO1Url;
            } else if (await fileExist (PSEUDO2Url) == true){
                 kmzUrl = PSEUDO2Url;
            } else {
                kmzUrl = "";
            }
     
            var kmzLayer = new google.maps.KmlLayer(kmzUrl);
            kmzLayer.setMap(map);
            console.log("URL: " + kmzUrl);
        [...]
    }
    La fonction initmap() étant à présent asynchrone, elle sera exécutée en « parallèle » avec le reste du code (ce n’est pas vraiment du multi-thread, mais on peut faire l’approximation). C’est un peu comme si tu exécutais du code avec setTimeout(() => { /* du code */ }, 0). Garde ça à l’esprit. Si tu as du code après initmap() qui a besoin de quelque chose que fait initmap(), il vaut mieux placer le script tout entier dans une fonction async.

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    320
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 320
    Points : 79
    Points
    79
    Par défaut
    Bonjour psychadelic et Watilin ,

    @Watilin
    J'ai mis en oeuvre le code que tu m'as indiqué et bien sur ça fonctionne au top, merci.
    J'ai lu et relu la méthode des promesses je crois comprendre le fonctionnement en revanche j'aurais été incapable de le mettre en oeuvre tout seul (la syntaxe avec => m'était complètement inconnue ...)
    Je vais la garder bien précieusement cette fonction fileExist(), elle devrait même être épinglée quelque part en remplacement de la version dépréciée, ce qui aiderait bien les noobs comme moi.

    Je passe en résolue, merci d'avoir pris le temps de m'expliquer la méthode, c'est cool


    PS: Je reviens sur mon erreur
    Code JS : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    else if (xhr.status !== 200 || xhr.status !== 404) {
        console.log("Error - Status: " + xhr.status);
        resolve(false);
    }
    Si je comprends bien c'est plutôt un && que j'aurais du mettre ? (ou le laisser sans conditions comme tu l'as fait)

  5. #5
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Points : 6 755
    Points
    6 755
    Par défaut
    Citation Envoyé par rlelamer Voir le message
    (la syntaxe avec => m'était complètement inconnue ...)
    Pardon si ça t’a embrouillé, les fonctions fléchées ne sont pas indispensables pour faire fonctionner les promesses. Elles sont équivalentes à une function classique tant qu’on n’utilise pas this.

    Citation Envoyé par rlelamer Voir le message
    Je vais la garder bien précieusement cette fonction fileExist(), elle devrait même être épinglée quelque part en remplacement de la version dépréciée, ce qui aiderait bien les noobs comme moi.
    Où se trouve la version dépréciée ? Avec de la chance, c’est dans un wiki ou un repo de pages Github et on peut proposer une mise à jour.

    Citation Envoyé par rlelamer Voir le message
    Si je comprends bien c'est plutôt un && que j'aurais du mettre ? (ou le laisser sans conditions comme tu l'as fait)
    Oui, et oui. Quand on « négationne » un ET, ça devient un OU et réciproquement, selon les lois de De Morgan.
    Et vu que les conditions status == 200 et status == 404 ont déjà été testées au-dessus, ça ne change rien de laisser le else seul, et c’est plus lisible

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    320
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 320
    Points : 79
    Points
    79
    Par défaut
    Pardon si ça t’a embrouillé, les fonctions fléchées ne sont pas indispensables pour faire fonctionner les promesses. Elles sont équivalentes à une function classique tant qu’on n’utilise pas this.
    Nan du tout c'est très intéressant, et j'ai gardé une chose en tête qui m'a été dite ici (sur ce forum) : " il n'y a pas qu'une solution possible pour obtenir ce que l'on souhaite ", par curiosité je vais essayé de le faire sans les fonctions fléchées, non pas que ça me plait pas mais pour voir si j'aurais pu le mettre en oeuvre par moi même en utilisant un code "classique". (Je le mettrait ici si j'y arrive, merci pour le lien sur les fonctions fléchées)


    Où se trouve la version dépréciée ? Avec de la chance, c’est dans un wiki ou un repo de pages Github et on peut proposer une mise à jour.
    J'ai pris l'habitude lorsque je recherche quelque chose de le faire en anglais sur Google, j'obtiens bien plus de résultats cohérents qu'une recherche en français
    Pour ce cas j'ai recherché " if file exist JS " sur Google et comme bien souvent ... on tombe sur le site (je le mets mais si la modération ne souhaite pas de liens extérieurs, ils l'enlèveront je comprendrais) de stackoverflow.
    Je suis parti de cette réponse.
    J'essaye toujours de mettre en oeuvre une solution en JS pure, lors des précédentes recherches j'étais tombé par hasard sur le site de VanillaJS qui montrait les performances du JS pure vs JQuery par exemple. Je ne suis pas assez calé pour en être au stade d'avoir un code super performant mais j'essaye de ne pas faire appel aux librairies externes qui souvent offrent une facilité de mise en oeuvre.


    Oui, et oui. Quand on « négationne » un ET, ça devient un OU et réciproquement, selon les lois de De Morgan.
    Et vu que les conditions status == 200 et status == 404 ont déjà été testées au-dessus, ça ne change rien de laisser le else seul, et c’est plus lisible
    Tout lu et tout compris, merci pour la solution et les conseils qui vont avec. J'ai appris pleins de choses entre hier et aujourd'hui

  7. #7
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 094
    Points : 6 755
    Points
    6 755
    Par défaut
    Citation Envoyé par rlelamer Voir le message
    Je suis parti de cette réponse.
    D’accord, c’est StackOverflow. Tout le monde peut éditer, mais vu l’âge de la réponse (2012), je ne crois pas que ce soit vraiment utile. StackOverflow devrait indiquer les dates de manière plus lisible… :/

    Autre chose : je ne sais pas pourquoi je n’ai pas pensé à fetch() hier… Je devais être fatigué
    fetch() c’est une évolution de XMLHttpRequest qui renvoie nativement des promesses. Idéal dans le cas présent !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    async function fileExist(url) {
        const response = await fetch(url, { method: "HEAD" });
     
        if (response.status === 200) {
            console.log("File exist");
            return true;
        } else if (response.status === 404) {
            console.log("File does not exist");
            return false;
        } else {
            console.log("Error - Status: " + response.status);
            return false;
        }
    }
    Remarque, on ne construit plus explicitement une promesse, mais la fonction est désormais async. Du coup j’ai (re)remplacé les resolve() par des return, et il n’y a rien à changer dans le reste du code, les await feront leur boulot comme avant. (Techniquement, c’est parce qu’une fonction async renvoie implicitement une promesse.)

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Mars 2011
    Messages
    320
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2011
    Messages : 320
    Points : 79
    Points
    79
    Par défaut
    Merci Watilin ,

    Ce code
    Code JS : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    async function fileExist(url) {
        const response = await fetch(url, { method: "HEAD" });
     
        if (response.status === 200) {
            console.log("File exist");
            return true;
        } else if (response.status === 404) {
            console.log("File does not exist");
            return false;
        } else {
            console.log("Error - Status: " + response.status);
            return false;
        }
    }
    Je le comprends plus facilement que ta première solution, il est plus à la portée de mes piètres connaissances en JS.
    Je garde les 2 solutions (j'en commenterais une, celle avec la syntaxe fléchée) et si un jour je tombe sur quelqu'un qui galère (comme moi) je partagerais ton code en n'oubliant pas de citer.
    Merci pour tout

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [thread] synchronize ou pas ?
    Par dvarrel dans le forum Langage
    Réponses: 4
    Dernier message: 26/07/2004, 19h09
  2. [Astuce][Thread]Utilisation des blocs synchronized
    Par Pill_S dans le forum Concurrence et multi-thread
    Réponses: 14
    Dernier message: 21/07/2004, 14h14
  3. [deprecated][surcharge] je veux enlever l'avertissement
    Par divxdede dans le forum Langage
    Réponses: 6
    Dernier message: 19/07/2004, 09h05
  4. [Thread] Synchronize
    Par Pedro dans le forum Langage
    Réponses: 9
    Dernier message: 06/07/2004, 13h30
  5. Réponses: 6
    Dernier message: 25/03/2002, 21h11

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo