Partage
  • Partager sur Facebook
  • Partager sur Twitter

AJAX et geocoding en masse

Faire un callback unique pour plusieurs requêtes AJAX ?

    20 mars 2017 à 16:27:55

    Bonjour,

    Je développe une appli web assez complexe qui entre autre utilise l'api web Google Map pour afficher la position d'une liste de personnes sur la carte.

    Pour mettre un marqueur sur la carte je dois connaitre les coordonnées latitude/longitude, et au départ ce que je connais c'est le nom de la ville. J'utilise donc le service geocode de google, avec l'algorithme AJAX de ce cours.

    Pour simplifier on va dire qu'au départ j'ai ça :

    entree = [{
    	nom: 'Nicolas',
    	ville: 'Brest, France'
    }, {
    	nom: 'Samy',
    	ville: 'Brest, France'
    }, {
    	nom: 'Marie',
    	ville: 'Lyon, France'
    }, {
    	nom: 'Giselle',
    	ville: 'Montpellier, France'
    }];

    Et je dois obtenir ça :

    sortie = [{
    	nom: 'Nicolas et Samy',
    	ville: 'Brest, France',
    	localisation: {
    		"lat": 48.390394,
    		"lng": -4.486076
    	}
    }, {
    	nom: 'Marie',
    	ville: 'Lyon, France',
    	localisation: {
    		"lat": 45.764043,
    		"lng": 4.835659
    	}
    }, {
    	nom: 'Giselle',
    	ville: 'Montpellier, France',
    	localisation: {
    		"lat": 43.610769,
    		"lng": 3.876716
    	}
    }];

    Pour ensuite afficher les marqueurs. Notez que comme Nicolas et Samy habitent la même ville, ils seront sur le même marqueur.

    Un algorithme simple serait de faire un forEach sur le tableau d'entrée, et pour chaque personne faire la requête AJAX, et en callBack ajouter le résultat au tableau de sortie.

    Le problème avec cette méthode est en fait un problème d'optimisation : dans cet exemple puisque la même ville reviens 2 fois, il est inutile d'envoyer deux fois la même requête AJAX pour obtenir les coordonnées. Ça n'a l'air de rien, mais je peux avoir des milliers de noms dans le tableau, pour en moyenne 5-6 fois moins de villes, donc je veux réduire le nombre d'appel AJAX pour réduire le temps d'exécution du code, et aussi éviter de dépasser le quota de l'API web.

    Une idée que j'ai eu est de faire une fonction qui va s'occuper d'abord de localiser toutes les villes et de stocker les résultat dans un nouveau tableau appelé "villes".

    Le problème est : comment savoir le moment où toutes les requêtes sont terminées, pour continuer l'execution du programme ? (en fait comment faire un callback unique pour plusieurs requêtes...)

    Si quelqu'un sait comment faire, je lui en serait très reconnaissant !

    Notez que pour le moment, j'ai programmé un truc qui fonctionne mais qui fait les requêtes AJAX l'une après l'autre, sauf qu'ainsi je perd l'intérêt de l'asynchrone, c'est donc très long : 1min20 pour localiser 160 villes par exemple. Je pense qu'il y a moyen de réduire ce temps par 3 en lançant plusieurs requêtes AJAX à la fois.

    • Partager sur Facebook
    • Partager sur Twitter
      20 mars 2017 à 17:53:09

      Bonjour,

      Les données des utilisateurs, ou sont ils stocké ?

      Pourquoi ne pas gérer simplement en javascript, avec une boucle for et if() en utilisant la fonction in_array() sur un tableau que tu remplies à chaque vérification ?

      Ou alors tu ne peux pas modifier t'es données en JS ?

      • Partager sur Facebook
      • Partager sur Twitter
        21 mars 2017 à 9:54:17

        Les données en entrée viennent d'un fichier soumis par l'utilisateur (api file).

        in_array() je vois que c'est une fonction PHP ? Ma question est sur le javascript car je traite tout côté client, mais je pense voir ce que tu veux dire, j'ai déjà testé un truc comme ça mais ça ne fonctionnais pas.

        Par exemple si je fais un forEach sur le tableau entree :

        Pour Nicolas, j'enregistre {lieu: "Brest", location: null} dans un tableau "villes", je lance l'appel AJAX pour localiser la ville, et en callback en plus d'ajouter nicolas au tableau sortie, j'ajoute la localisation (je remplace le null par {lat: 48.etc, lng:-4.etc}).

        Ensuite pour Samy, je vois qu'il y déjà "Brest" dans le tableau "villes", mais location est toujours "null" car la requête AJAX n'est pas encore terminée (puisqu'elle est asynchrone). Comment peut-on, pour Samy, attendre la fin de l'AJAX lancé pour Nicolas ?

        -
        Edité par thelinekioubeur 21 mars 2017 à 10:16:58

        • Partager sur Facebook
        • Partager sur Twitter
          22 mars 2017 à 15:12:31

          Bonjour,

          Pour paralléliser, vous pouvez utiliser une librairie comme celle la : https://github.com/caolan/async. Vous pouvez par exemple lancer plusieurs requêtes en parallèle et définir un callback qui sera exécuté quand toutes les requêtes seront terminées.

          • Partager sur Facebook
          • Partager sur Twitter
            22 mars 2017 à 23:37:36

            Merci ! Je vais regarder ça.
            • Partager sur Facebook
            • Partager sur Twitter
              24 mars 2017 à 19:35:15

              Bon ça marche bien. (ou presque)

              Le soucis que j'ai  maintenant, comme j'envoie toutes les requêtes en même temps, c'est ça dépasse de quota de l'API qui est de 30 requêtes par seconde. (et 2500 par jour mais osef pour le moment)

              Quelle est la méthode habituelle pour gérer une limitation par seconde ? J'ai essayé de faire une requête chaque trentième de seconde, mais c'est con car comme les requêtes sont faites côté client, si plusieurs utilisateurs utilisent le site au même moment, ça sert à rien.

              • Partager sur Facebook
              • Partager sur Twitter
                4 avril 2017 à 9:52:12

                Bonjour,

                Je ne vois pas comment gérer cette limitation coté client. Dans ce cas je ferais un backend qui ferait proxy et qui pourrait gérer cette limitation de manière centralisée. Mais rendu la, quitte a faire un back-end, plutôt que faire un proxy vers l'API google, autant développer sois même un petit service de géocodage en se basant sur des données en opendata

                Sinon il y a aussi adresse.data.gouv.fr qui fait du géocodage et n'a il me semble, pas de limitation, ils demandent juste une utilisation raisonnée du service. 

                • Partager sur Facebook
                • Partager sur Twitter
                  4 avril 2017 à 14:58:33

                  Merci pour ces infos, je vais essayer cette api pour voir, mais je pense que ça ne conviendra pas :

                  - J'ai besoin d'un geocoding international, cette api et ces données dont tu parles semblent n'être que nationales.

                  - Je pense que l'api de google est la meilleure grâce à son algorithme qui corrige les petites erreurs ou les "syntaxes" variées (ex : "caen france" doit fonctionner aussi bien que "caen, calvados, france" etc...). Les noms de lieux sont écris manuellement par l'utilisateur à travers un logiciel tiers, je n'ai donc pas de contrôle dessus.

                  Par exemple j'avais déjà essayé l'api de openstreetmap (qui n'a pas de limitation), mais beaucoup de lieux ne sont pas trouvés, parfois c'est juste car le nom d'un hameau est spécifié, en plus du nom de la commune...

                  En attendant j'ai trouvé une autre solution pour gérer la limitation : j'envoie toutes les requêtes d'un coup, et chaque requête refusée est renvoyée une seconde plus tard, et ainsi de suite jusqu'à ce que ça passe. C'est bourrin, mais ça passe :ninja:

                  -
                  Edité par thelinekioubeur 4 avril 2017 à 15:02:55

                  • Partager sur Facebook
                  • Partager sur Twitter
                    6 avril 2017 à 11:35:32

                    Oui la solution que je mentionne ne fonctionne qu'au niveau national. Du coup il reste la solution du proxy, ça se fait très bien en nodeJS qui est fait pour ça : très bonne gestion des flux de données et facilité de faire un petit serveur web.

                    Si vous êtes le seul à utiliser ce que vous faites, on peut même se passer de backend et faire la limitation (throttling en anglais) coté client. Une librairie comme celle la peut aider.

                    • Partager sur Facebook
                    • Partager sur Twitter

                    AJAX et geocoding en masse

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown