[NODEJS] annuler 2meme requete sur un get

annuler 2meme requete sur un get [NODEJS] - Javascript/Node.js - Programmation

Marsh Posté le 02-04-2017 à 21:28:52    

Bonsoir,
 
 
débutant nodejs, je découvre les joies de l'asychrone et des callbacks. Pour le moment je suis confronté à un "probleme" génant  après un GET http sur une API Json qui envoie 2 resultat identiques.
Au début j'ai cru à un bug, mais après investigations, ils s'avère donc qu'il sagit d'un comportement normal, puisque le resultat de la première requete contient le favicon et le données et la l2eme, les mêmes données.
 
J'ai pas mal cherché sur le net avant de poster ici, mais je n'ai pas trouvé de solution satisfaisante (notez que c'est peut-etre moi qui ne parvient pas à l'implémenter correctement  :whistle: ).
 
Il ya donc next qui est censée passée directement à la 2eme requete, mais malheuresusement ca ne fonctionne pas.
 

Code :
  1. var url = "https://superwebservice";
  2.             rest.get(url)
  3.                 //request success
  4.                 .on("200", function (request, next)
  5.                 {
  6.                     if (request.url === '/favicon.ico') {
  7.                         res.writeHead(200, { 'Content-Type': 'image/x-icon' });
  8.                         res.end(/* icon content here */);
  9.                     }else{
  10.                         next;
  11.                        
  12.                     }
  13.                     console.log(request[0]);
  14.                        
  15.                 });


 
Vous auriez des idées, pour éviter que je reçoive 2 x les mêmes données ?
Peut-on configurer cela sur le server de l'API tant qu'à faire ?
 
Merci pour vos réponses  :)  
 
Tom

Reply

Marsh Posté le 02-04-2017 à 21:28:52   

Reply

Marsh Posté le 03-04-2017 à 13:10:59    

Tu peux modifier ton service?
 
http://stackoverflow.com/questions [...] avicon-ico


---------------
sheep++
Reply

Marsh Posté le 03-04-2017 à 14:42:34    


A priori oui.
 
Ce qui m'étonne c'est que le phénomène ne se produit qu'avec Nodejs:
la même requete faite avec firefox me donne bien les données non dupliquées. (j'ai vérifié avec l'outil de debuggage).


Message édité par tompouss le 03-04-2017 à 14:44:11

---------------
collectionneur de pâtes thermiques
Reply

Marsh Posté le 04-04-2017 à 13:00:48    

Bonjour,
 
Je suis intrigué par le soucis. Il n'y a pas de raison que cela n'arrive qu'avec Nodejs.
Peux-tu expliquer d'où vient la variable rest ?
As-tu ajouté un header particulier ?
 
Et pourquoi ne pas faire comme la doc le propose:  

Code :
  1. rest.get(url).on('data', callback);


au lieu de  

Code :
  1. rest.get(url).on('200', callback);


https://nodejs.org/en/docs/guides/a [...] ansaction/  
 
Tor

Message cité 1 fois
Message édité par torwood3 le 04-04-2017 à 13:02:40

---------------
"La valeur d'un homme tient dans sa capacité à donner et non dans sa capacité à recevoir." Albert Einstein / "Dans la nature, tout a toujours une raison. Si tu comprends cette raison, tu n'as plus besoin de l'expérience." Léonard De Vinci
Reply

Marsh Posté le 04-04-2017 à 16:34:29    

torwood3 a écrit :

Bonjour,
 
Je suis intrigué par le soucis. Il n'y a pas de raison que cela n'arrive qu'avec Nodejs.
Peux-tu expliquer d'où vient la variable rest ?
As-tu ajouté un header particulier ?
 
Et pourquoi ne pas faire comme la doc le propose:  


 
 
la variable rest est l'object quicontient des methodes du module restler
 
https://github.com/danwrong/restler
 
 
en fait j'ai essayé avec le module request mais le problème est le même


Message édité par tompouss le 04-04-2017 à 16:35:29

---------------
collectionneur de pâtes thermiques
Reply

Marsh Posté le 05-04-2017 à 09:01:32    

Bonjour,
 
Je resigne, ton soucis est vraiment étrange.
Le double appel fais pour récupérer le Favicon est un comportement normal pour les navigateurs. Les modules "request", "http", "restler" et compagnie n'ont aucun raison de l'implémenter car ce n'est pas leur objectif.
 
En relisant ton code, trois remarques :
 - La promise de reslter te retourne qu'une seule variable (data)
 - Next est dans ton code une callback (une function), il lui faut donc des parenthèses pour se lancer. (mais elle a pas sa place)
- Je n'ai pas vu que "restler" avait implémenté l'évènement "200". J'ai vu que des "complete". J'ai lu !   :pt1cable:  
 
J'ai l'impression qu'il y a eu une petite confusion sur le type de retour que te propose "reslter". Les deux arguments sont "data", c'est à dire le body de la réponse et "response" qui j'imagine est la requête réponse en entier (header, statusCode and co ...). Il n'y a donc pas de next.
 
next lorsque tu traites les requêtes reçu par nodejs. Dans ce cas tu as trois argument possible : req, res et next
Mais ici c'est toi qui initie la requête.
 
Si ton soucis n'est toujours pas réglé, peux-tu tester ce code et me dire l'affichage correspondant dans la console. Merci bien  
 

Code :
  1. var url = "https://superwebservice";
  2. var i = 0;
  3. rest.get(url).on("complete", function (data, response) {
  4.    console.log("--------------------------------" ); 
  5.    console.log("ID Req : " + i);
  6.    console.log(data);
  7.    console.log(response);
  8. });


 
Edit : Mise en forme


Message édité par torwood3 le 05-04-2017 à 09:33:23

---------------
"La valeur d'un homme tient dans sa capacité à donner et non dans sa capacité à recevoir." Albert Einstein / "Dans la nature, tout a toujours une raison. Si tu comprends cette raison, tu n'as plus besoin de l'expérience." Léonard De Vinci
Reply

Marsh Posté le 05-04-2017 à 10:26:31    

ESSAI 1
 
 
script_modifié:
 
 

Code :
  1. const rest = require("restler";);
  2. const converter = require("./monserviceweb-converter";);
  3. const utils = require("../utils";);
  4. const mongoose = require("mongoose";);
  5. exports.id = "monserviceweb";
  6. exports.name = "monserviceweb";
  7. exports.region = ["uy", "ar"];
  8. exports.idPrefix = "monserviceweb_";
  9. const regionMap = ["ar", "uy"];
  10. exports.createService = function () {
  11.     var service = {
  12.         getDataFromAllCountries: function () {
  13.             /*offset = offset ? offset : 0;
  14.             limit = limit ? limit : 500;*/
  15.             var url = "https://monserviceweb.com";
  16.             rest.get(url)
  17.                 //request success
  18.                 .on('complete', function (data) {
  19.                     console.log(data);
  20.                 })
  21.         }()
  22.     }
  23. }();


OUTPUT :  

Code :
  1. Info: Start process (9:59:29 AM)
  2. [ { countryId: 1,
  3.     name: 'Uruguay',
  4.     iso2: 'UY',
  5.     iso3: 'URY',
  6.     phoneCode: '+598',
  7.    
  8.   { countryId: 2,
  9.     name: 'Argentina',
  10.     iso2: 'AR',
  11.     iso3: 'ARG',
  12.     phoneCode: '+54',
  13.  
  14. [ { countryId: 1,
  15.     name: 'Uruguay',
  16.     iso2: 'UY',
  17.     iso3: 'URY',
  18.     phoneCode: '+598',
  19.    
  20.   { countryId: 2,
  21.     name: 'Argentina',
  22.     iso2: 'AR',
  23.     iso3: 'ARG',
  24.     phoneCode: '+54',
  25.  
  26. Info: End process (9:59:30 AM)


----------------------------------------------------------------
autre script
 
 

Code :
  1. const rest = require("restler";);
  2. const converter = require("./monserviceweb-converter";);
  3. const utils = require("../utils";);
  4. const mongoose = require("mongoose";);
  5. exports.id = "monserviceweb";
  6. exports.name = "monserviceweb";
  7. exports.region = ["uy", "ar"];
  8. exports.idPrefix = "monserviceweb_";
  9. const regionMap = ["ar", "uy"];
  10. exports.createService = function () {
  11.     var service = {
  12.         getDataFromAllCountries: function () {
  13.             /*offset = offset ? offset : 0;
  14.             limit = limit ? limit : 500;*/
  15.             var url = "https://monserviceweb.com";
  16.             var i = 0;
  17.             rest.get(url).on("200", function (result) {
  18.                 console.log("--------------------------------";);
  19.                 console.log("ID Req : " + i);
  20.                 console.log(result);
  21.              
  22.             });
  23.                
  24.         }()
  25.     }
  26. }();


OUTPUT

Code :
  1. Info: Start process (9:56:07 AM)
  2. [ { countryId: 1,
  3.     name: 'Uruguay',
  4.     iso2: 'UY',
  5.     iso3: 'URY',
  6.     phoneCode: '+598',
  7.  
  8.   { countryId: 2,
  9.     name: 'Argentina',
  10.     iso2: 'AR',
  11.     iso3: 'ARG',
  12.     phoneCode: '+54',
  13.  
  14. --------------------------------
  15. ID Req : 0
  16. [ { countryId: 1,
  17.     name: 'Uruguay',
  18.     iso2: 'UY',
  19.     iso3: 'URY',
  20.     phoneCode: '+598',
  21.  
  22.   { countryId: 2,
  23.     name: 'Argentina',
  24.     iso2: 'AR',
  25.     iso3: 'ARG',
  26.     phoneCode: '+54',
  27.    
  28. Info: End process (9:56:09 AM)


Essai 2
 
 

Code :
  1. const rest = require("restler";);
  2. const converter = require("./monserviceweb-converter";);
  3. const utils = require("../utils";);
  4. const mongoose = require("mongoose";);
  5. exports.id = "monserviceweb";
  6. exports.name = "monserviceweb";
  7. exports.region = ["uy", "ar"];
  8. exports.idPrefix = "monserviceweb_";
  9. const regionMap = ["ar", "uy"];
  10. exports.createService = function () {
  11.     var service = {
  12.         getDataFromAllCountries: function () {
  13.             /*offset = offset ? offset : 0;
  14.             limit = limit ? limit : 500;*/
  15.             var url = "https://monserviceweb.com";
  16.             var i = 0;
  17.             rest.get(url).on("complete", function (result) {
  18.                 console.log("--------------------------------";);
  19.                 console.log("ID Req : " + i);
  20.                 console.log(result);
  21.              
  22.             });
  23.                
  24.         }
  25.     }
  26. }();


Resultat
 

Code :
  1. Info: Start process (10:02:46 AM)
  2. [ { countryId: 1,
  3.     name: 'Uruguay',
  4.     iso2: 'UY',
  5.     iso3: 'URY',
  6.     phoneCode: '+598',
  7.   { countryId: 2,
  8.     name: 'Argentina',
  9.     iso2: 'AR',
  10.     iso3: 'ARG',
  11.     phoneCode: '+54',
  12. Info: End process (10:02:48 AM)


ESSAI 3
 

Code :
  1. const rest = require("restler";);
  2. const converter = require("./monserviceweb-converter";);
  3. const utils = require("../utils";);
  4. const mongoose = require("mongoose";);
  5. exports.id = "monserviceweb";
  6. exports.name = "monserviceweb";
  7. exports.region = ["uy", "ar"];
  8. exports.idPrefix = "monserviceweb_";
  9. const regionMap = ["ar", "uy"];
  10. exports.createService = function () {
  11.     var service = {
  12.         getDataFromAllCountries: function () {
  13.             /*offset = offset ? offset : 0;
  14.             limit = limit ? limit : 500;*/
  15.            var url = "https://monserviceweb.com";
  16.             var i = 0;
  17.             rest.get(url).on("test", function (result) {
  18.                 console.log("--------------------------------";);
  19.                 console.log("ID Req : " + i);
  20.                 console.log(result);
  21.              
  22.             });
  23.                
  24.         }()
  25.     }
  26. }();


Resultat

Code :
  1. Info: Start process (10:03:56 AM)
  2. [ { countryId: 1,
  3.     name: 'Uruguay',
  4.     iso2: 'UY',
  5.     iso3: 'URY',
  6.     phoneCode: '+598',
  7.   { countryId: 2,
  8.     name: 'Argentina',
  9.     iso2: 'AR',
  10.     iso3: 'ARG',
  11.     phoneCode: '+54'
  12. Info: End process (10:03:59 AM)


ESSAi 4
 
 

Code :
  1. const rest = require("restler";);
  2. const converter = require("./monserviceweb-converter";);
  3. const utils = require("../utils";);
  4. const mongoose = require("mongoose";);
  5. exports.id = "monserviceweb";
  6. exports.name = "monserviceweb";
  7. exports.region = ["uy", "ar"];
  8. exports.idPrefix = "monserviceweb_";
  9. const regionMap = ["ar", "uy"];
  10. exports.createService = function () {
  11.     var service = {
  12.         getDataFromAllCountries: function () {
  13.             /*offset = offset ? offset : 0;
  14.             limit = limit ? limit : 500;*/
  15.            var url = "https://monserviceweb.com";
  16.             rest.get(url)
  17.                 //request success
  18.                 .on('test', function (data) {
  19.                     console.log(data);
  20.                 })
  21.         }()
  22.     }
  23. }();


Resultat

Code :
  1. Info: Start process (10:05:53 AM)
  2. Info: End process (10:05:55 AM)


Conclusion:
 
 
ne serais-ce pas les () à la fin de getDataFromAllCountries qui provoquerait ces doublons de données ?
Mais si je les enlève, rien ne s'affiche
 

Code :
  1. getDataFromAllCountries: function () {
  2.          
  3.         }()


 en javascript, je suppose que le ";" est comparable au die() en PHP: on force la fin du script


Message édité par tompouss le 05-04-2017 à 10:27:42

---------------
collectionneur de pâtes thermiques
Reply

Marsh Posté le 05-04-2017 à 11:04:05    

Salut,
 
Merci pour les essais.
Le ";" indique la fin d'une instruction. Il est nécessaire lorsqu'il y a plusieurs instruction dans la même ligne mais optionnel sinon.  
Toute fois, je t'incite à le mettre :)
Ca n'a rien a voir avec le die() de php.
 
On voit clairement que javascript est un langage super tolérant :
Enlève les ";" de tes parenthèse  

Code :
  1. const mongoose = require("mongoose";);


devient

Code :
  1. const mongoose = require("mongoose" );


 
Quand tu mets un () après un function() {}, tu demandes au code d’exécuter cette fonction à l’instanciation du code. C'est à dire dès que le code est lu par la machine.
 
Je comprends pas trop le besoin d'exporter toutes ces variables.
 

Code :
  1. var app = function () {
  2.     var i = 0;
  3.     var service = {
  4.         getDataFromAllCountries: function () {
  5.             /*offset = offset ? offset : 0;
  6.             limit = limit ? limit : 500;*/
  7.             var url = "https://monserviceweb.com";
  8.             rest
  9.                 .get(url)
  10.                 .on('test', function (data) {
  11.                     console.log(i);
  12.                     i++; //Petit oubli de la derniere fois :)
  13.                     console.log(data);
  14.                 })
  15.         }
  16.     }
  17.    return service;
  18. };
  19. var myApp = app();
  20. myApp.getDataFromAllCountries();


 
Je remarque que le console.log("---------" ); n'est pas toujours affiché même lorsqu'il est présent dans la callback (essai1). Etrange  :pfff:  
Tor


Message édité par torwood3 le 05-04-2017 à 11:11:36

---------------
"La valeur d'un homme tient dans sa capacité à donner et non dans sa capacité à recevoir." Albert Einstein / "Dans la nature, tout a toujours une raison. Si tu comprends cette raison, tu n'as plus besoin de l'expérience." Léonard De Vinci
Reply

Marsh Posté le 05-04-2017 à 11:30:41    

[table][tr][td]
[/td][/tr][/table]C'est bien ce qui m'agace avec javascript: son côté ultra permissif, à ajouter à l'ambiguité de certaines fonctions.
Moi qui aime que les choses soient claires, carrées (et la logique de la POO), à ce niveau, javascript est encore pire que PHP  :cry: .
 
En fait j'ai été chargé d'implémenter une fonctionnalité d'importation de données dans une application Nodejs existante et développée par des personnes expérimentées (bien plus que moi), mais qui, pour le moment, sont occupées sur un autre projet.
Cette application est très structurée et contient de nombreux fichiers pour bien séparer le rôle des scripts.
En gros l'application comprend des taches pour charger des données venant de webservices (FTP, Json, etc..), les normaliser et les insérer en base de  données (NosSQL) via un ORM (mongoose).
 
C'est pour ca qu'il ya énormément d'exports.


Message édité par tompouss le 05-04-2017 à 11:31:55

---------------
collectionneur de pâtes thermiques
Reply

Marsh Posté le 05-04-2017 à 11:54:04    

Ouai javascript c'est une vrai saloperie si le code n'est pas bien structuré.
 
Et pour moi qui vient du C puis POO (java, python), certains concepts sont vraiment obscurs.  
Par exemple

Code :
  1. var self = this


 
Eurk  [:cerveau pouah]


---------------
sheep++
Reply

Marsh Posté le 05-04-2017 à 11:54:04   

Reply

Marsh Posté le 05-04-2017 à 13:57:33    

Merci pour vos explications
 
maintenant j'ai un autre probleme, qui est d'accéder aux données de ce script:
 
via un autre script (situé dans un répertoire test)
 

Code :
  1. const async = require("async";);
  2. const db = require("../db/db";);
  3. const utils = require("../utils";);
  4. const monwebservice = require("../provider/monwebservice-dataprovider";); // importation du script précédent
  5. var monwebservice_import = monwebservice.createService;
  6. var service = monwebservice_import.service;
  7. console.log(service.getDataFromAllCountries());


Resultat: undefined  :cry:


Message édité par tompouss le 05-04-2017 à 13:58:31

---------------
collectionneur de pâtes thermiques
Reply

Marsh Posté le 05-04-2017 à 16:07:59    

Ca fonctionne ? :)
 
Tu peux expliquer ce que tu exportes ?
 
Si c'est basé sur le code proposé, le soucis vient de la ligne 8.
Il faut exécuter la fonction "createService".
Et tant qu'on y est, en complément de var on a introduit dans la nouvelle version de JS (ES6) les types "let" et "const"
 
"let" remplace var pour les variables qui vont être modifié. "const" pour les variables qui ne seront pas modifié (une constante). Pense donc a harmoniser ton code.
 

Code :
  1. const monwebservice_import = monwebservice.createService();


 
Euh ...  :non:
Tu t'attends à voir les données affichés avec le console log ?
En basant de ce qui a été montré plus tot (requête get), on se trouve dans une situation asynchrone.
Potentiellement, le console.log va être exécuté AVANT que t'a requête soit fini. Bienvenu en JavaScript  :sol:  
Modulo le faite que tu ne retournes rien de la fonction "getDataFromAllCountries", c'est une source de soucis.
 
Je pense qu'il va falloir faire un zeste de gymnastique intellectuelle pour introduire l'asynchrone dans ce que tu comptais faire.
La solution la plus simple que je vois, c'est d'utiliser une callback :p (Sinon, faut regarder les promises, async/wait)
 
En gros, tu fais un truc comme ca :

Code :
  1. //Dans monwebservice-dataprovider.js
  2. ...
  3. getDataFromAllCountries: done => {
  4.     var url = "https://monserviceweb.com"; 
  5.     rest.get(url).on('complete', (data, response)  => {
  6.         //transformation, verification de data  
  7.         if (response = error) //Tester si c'est une erreur
  8.             done(null, error);
  9.         else
  10.             done(data, null);
  11.         });
  12. }
  13. ...


 et  

Code :
  1. var monwebservice_import = monwebservice.createService();
  2. var service = monwebservice_import.service;
  3. ...
  4. //Et quand tu manipules les données.
  5. service.getDataFromAllCountries((data,err) => {
  6.    if(!err) {
  7.       console.log("Oups, error : " + err);
  8.       return //ou throw Error etc...
  9.    }
  10.  
  11.    //Manipuler les données qui se trouvent dans la variable data
  12. });


 
Pour info

Code :
  1. () => {} === function() {}

, "arrow function" introduit dans ES6.  
 
Tu vois l'enchainement logique. On donne une callback a exécuter quand la requête se sera exécuté et on propage l'erreur :)
Et pour vos remarques sur le JS  :kaola:  !!! On fait avec ce qu'on a dans les navigateurs hein !
 
Je vois aussi que les ";" sont aussi présent dans tes imports :

Code :
  1. const async = require("async";);
  2. const db = require("../db/db";);
  3. const utils = require("../utils";);

 
Il y a une raison particulière ?  
C'est la première fois que je vois ca.
 

Code :
  1. const async = require("async" );
  2. const db = require("../db/db" );
  3. const utils = require("../utils" );


Message édité par torwood3 le 05-04-2017 à 16:40:07

---------------
"La valeur d'un homme tient dans sa capacité à donner et non dans sa capacité à recevoir." Albert Einstein / "Dans la nature, tout a toujours une raison. Si tu comprends cette raison, tu n'as plus besoin de l'expérience." Léonard De Vinci
Reply

Marsh Posté le 05-04-2017 à 17:28:29    

pour les ; dans les imports
 
const utils = require("../utils"; );
 
 
je sais pas d'où ca vient: j'ai bien cette syntaxe dans mon code
 
const utils = require("../utils" ) ;
 
 
 
Mais ca avance:
 
 
je parviens enfin à récupérer mes données dans le fichier test-monserviceweb-dataprovide.js :)
 
 
par contre je comprends pas ce qu'est le callback done?
C'est un truc natif à node je suppose ?
 
 
 
Un grand merci pour votre aide en tout cas :)


Message édité par tompouss le 05-04-2017 à 17:43:39

---------------
collectionneur de pâtes thermiques
Reply

Marsh Posté le 05-04-2017 à 18:01:19    

Code :
  1. var monwebservice_import = monwebservice.createService();
  2.     var service = monwebservice_import.service;
  3.     ...
  4.     //Et quand tu manipules les données.
  5.    
  6.     const done = (data,err) => {
  7.        if(!err) {
  8.           console.log("Oups, error : " + err);
  9.           return //ou throw Error etc...
  10.        }
  11.    
  12.        //Manipuler les données qui se trouvent dans la variable data
  13.     };
  14.     service.getDataFromAllCountries(done);


---------------
"La valeur d'un homme tient dans sa capacité à donner et non dans sa capacité à recevoir." Albert Einstein / "Dans la nature, tout a toujours une raison. Si tu comprends cette raison, tu n'as plus besoin de l'expérience." Léonard De Vinci
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed