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 :

Boucle sur une fonction


Sujet :

JavaScript

  1. #1
    Nouveau candidat au Club
    Homme Profil pro
    Inscrit en
    Avril 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 2
    Par défaut Boucle sur une fonction
    Bonjour à tous,
    d'habitude je trouve mes réponses en cherchant, mais la... rien
    j'ai ce bout de script qui fonctionne (c'est sous greasemonkey, mais c'est à prioris assez proche de la fonction xmlhttprequest de base):


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    GM_xmlhttpRequest({
      method: "GET",
      url: urlnd[0],
      onload: function recup(response) {
        alert(nd[0]);
        alert(response.responseText);
      }
    });

    1ere question, peut on boucler cette fonction? (les tables urlnd et nd sont définies et fonctionne parfaitement) lorsque je fais une boucle for, ca ne m'affiche que la dernière, cause que j'ai compris puisque la fonction ce fait sur le onload

    2eme question, a quoi correspond l'argument response? puisque en mettant n'importe quoi (d'identique évidemment) sur les 2 lignes ca fonctionne toujours?

    3eme question, pourquoi lorsque je sors la fonction de cette facon:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function recup(response) {
        alert(nd[0]);
        alert(response.responseText);
      }
     
    GM_xmlhttpRequest({
      method: "GET",
      url: urlnd[0],
      onload: recup(response),
    });

    ca ne fonctionne pas, je n'ai meme pas le alert(nd[0] alors que je l'ai en supprimant l'argument:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function recup() {
        alert(nd[0]);
        alert(response.responseText);
      }
     
    GM_xmlhttpRequest({
      method: "GET",
      url: urlnd[0],
      onload: recup(),
    });

    il me semble que j'avais déja eu ce problème sur un script complètement différent, sur un onclick me semble t il, sans argument, aucun soucis, dès que je passais un argument ca bloquait.

    Merci d'avance pour vos réponses, remarques, et suggestions eventuelles

    Windows XP / Firefox 11.0

  2. #2
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    for(var i = 0; i < 10; i++){
      GM_xmlhttpRequest({
        method: "GET",
        url: urlnd[i],
        onload: function recup(response) {
          alert(nd[i]);
          alert(response.responseText);
        }
      });
    }
    Tu fais une boucle sur i qui ira de 0 a 10

    Pour chaque valeur de i, il fera un appel a GM_xmlhttpRequest.

    Les 10 appels se font en une fraction de seconde, maintenant ton i vaut 10.

    Un des 10 appels de GM_xmlhttpRequest recoit sa première réponse (une requête ajax donc, une page correspondant à l'url fourni).

    Tu as donc la fonction de callback/succes/onload qui se déclenche comme tu l'as définie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function recup(response) {
          alert(nd[i]);
          alert(response.responseText);
    }
    response devrait valoir la bonne page appelée comme voulu par contre ton i vaut 10, rappelle-toi.

    Donc un alert(nd[i]); équivaudra à alert(nd[10]); le dernière élément pour toutes les réponses que tu recevras du serveur.

    ---------------------

    Maintenant que tu as (je l'espère) compris le problème, je vais te proposer une des solutions le plus courante : l'encapsulation

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    for(var i = 0; i < 10; i++){
      (function(j){ // on déclare une fonction anonyme et on l'exécute directement
        GM_xmlhttpRequest({
          method: "GET",
          url: urlnd[j], // ici peu importe si on utilise "i" ou "j", cette fonction (GM_xmlhttpRequest) sera entièrement executée avant de passer au "i" suivant.
          onload: function recup(response) {
            alert(nd[j]); // le "j" étant déclaré individuellement à l'intérieur de chacune des 10 fonctions anonymes, sa valeur ne change pas avec la boucle for, chaque "j" garde sa valeur même longtemp après la fin de la boucle lorsque le onload recevra la réponse du serveur.
            alert(response.responseText);
          }
        });
      })(i); // on passe la valeur de i à chaque déclaration/exécution de notre nouvelle fonction
    }

    edit: ou mieux n'encapsuler que la partie qui sera exécutée à retardement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function bind_recup(j){
        return function(response){
            alert(nd[j]);
            alert(response.responseText);
        };
    }
     
    for(var i = 0; i < 10; i++){
        GM_xmlhttpRequest({
          method: "GET",
          url: urlnd[i], 
          onload: bind_recup(i)
        });
    }

  3. #3
    Nouveau candidat au Club
    Homme Profil pro
    Inscrit en
    Avril 2012
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2012
    Messages : 2
    Par défaut
    Merci pour ta réponse, effectivement j'avais cerné la cause de l'affichage de la dernière valeur uniquement, je n'ai pas étudiée ta solution mais elle me parait très bien expliquée, je verrais ca demain.

    Merci beaucoup

    Alors premiers essais, très concluants, merci
    Je ne comprends pas tout sachant que ceci fonctionne également:

    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
     
    function bind_recup(k){
        return function(response){
            alert(nd[k]);
            alert(response.responseText);
        };
    }
     
    for(var k = 0; k < 3; k++){
    GM_xmlhttpRequest({
      method: "GET",
      url: urlnd[k],
      onload: bind_recup(k)
    });
    }
    en fait c'est le fait de mettre une fonction dans une fonction?

    Re merci en tout cas

  4. #4
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2008
    Messages
    23 647
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Billets dans le blog
    20
    Par défaut
    Non !
    Tu ne peux pas faire ça.
    Voir : http://www.developpez.net/forums/d11...-cachees-eval/
    Pas de question technique par MP !
    Tout le monde peut participer à developpez.com, vous avez une idée, contactez-moi !
    Mes formations video2brain : La formation complète sur JavaScriptJavaScript et le DOM par la pratiquePHP 5 et MySQL : les fondamentaux
    Mon livre sur jQuery
    Module Firefox / Chrome d'intégration de JSFiddle et CodePen sur le forum

  5. #5
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    Citation Envoyé par toinounet21 Voir le message

    Merci beaucoup

    Alors premiers essais, très concluants, merci
    Je ne comprends pas tout sachant que ceci fonctionne également:

    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
     
    function bind_recup(k){
        return function(response){
            alert(nd[k]);
            alert(response.responseText);
        };
    }
     
    for(var k = 0; k < 3; k++){
    GM_xmlhttpRequest({
      method: "GET",
      url: urlnd[k],
      onload: bind_recup(k)
    });
    }
    en fait c'est le fait de mettre une fonction dans une fonction?

    Re merci en tout cas
    Un fait tu exécute une fonction (bind_recup) directement PENDANT la boucle qui elle renvoit une autre fonction qui sera assignée (liée) au "onload".

    Plus tard quand le "onload" (donc ton autre fonction) se déclenchera et que ton i (ou autre indice de ta boucle) n'aura plus la bonne valeur, ta fonction créée dans une autre aura toujours la bonne valeur (variable local à la capsule qui elle s'était instancié directement pendant la boucle).


    edit: en fait, dans mon exemple j'avais donné un nom différent à "i" et à "j" pour bien marquer le fait qu'on créé une nouvelle variable indépendante de celle qui nous donne sa valeur. (en fait une nouvelle variable (et fonction) est déclarée pour chaque itération de ta boucle "for", ça permet de conserver le contexte au moment du passage dans la boucle.)

    @Bovino: le code est tout à fait correct, si la fonction exécutée renvoit une autre fonction.

  6. #6
    Rédacteur

    Avatar de Bovino
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2008
    Messages
    23 647
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2008
    Messages : 23 647
    Billets dans le blog
    20
    Par défaut
    Citation Envoyé par Willpower
    @Bovino: le code est tout à fait correct, si la fonction exécutée renvoit une autre fonction.
    Tout à fait, ma remarque était essentiellement liée au code du premier message qui laisse supposer que toinounet21 ne différencie pas correctement la notion de fonction de rappel et celle d'appel de fonction
    Pas de question technique par MP !
    Tout le monde peut participer à developpez.com, vous avez une idée, contactez-moi !
    Mes formations video2brain : La formation complète sur JavaScriptJavaScript et le DOM par la pratiquePHP 5 et MySQL : les fondamentaux
    Mon livre sur jQuery
    Module Firefox / Chrome d'intégration de JSFiddle et CodePen sur le forum

  7. #7
    Membre Expert Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Par défaut
    Citation Envoyé par Bovino Voir le message
    Tout à fait, ma remarque était essentiellement liée au code du premier message qui laisse supposer que toinounet21 ne différencie pas correctement la notion de fonction de rappel et celle d'appel de fonction
    Ah juste, j'avais même pas remarqué cela dans son post initial

    donc @toinounet21

    dans ton code initial tu faisais
    ce qui n'avais aucun sens puisque tu passais au "onload" ... RIEN (car ta fonction "recup" n'a pas de return) alors que tu aurais du passer la fonction elle même (sans l'exécutée) :

    Note que dans mon exemple A MOI, tu dois bien laisser les parenthèses pour que la première fonction s'exécute et en renvoit une autre.

    J'espère qu'on t'aura aidé à mieux comprendre le principe, si t'as d'autres questions, n'hésite pas.

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

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 099
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    (function(j){
       ...
    })(i);
    Très belle closure Willpower, j'allais justement proposer une solution de ce genre, tu m'as coupé l'herbe sous le pied

    Sinon il s'agit d'un problème connu, excepté qu'ici on n'a pas de <div> auxquelles attacher notre indice de boucle. En fait c'est un problème qui survient dès lors qu'on a une fonction de rappel dans une boucle for.
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

Discussions similaires

  1. [XSLT] Faire une boucle sur une variable [i]
    Par PoT_de_NuTeLLa dans le forum XSL/XSLT/XPATH
    Réponses: 8
    Dernier message: 07/06/2010, 12h45
  2. Probleme sur une fonction vérif
    Par PrinceMaster77 dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 29/10/2004, 13h25
  3. Probleme de pointeur sur une fonction
    Par nicky78 dans le forum C
    Réponses: 2
    Dernier message: 23/05/2004, 20h26
  4. Erreur sur une fonction avec des paramètres
    Par Elois dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 05/05/2004, 21h00
  5. PerlDoc sur une fonction d'un module
    Par lesouriciergris dans le forum Modules
    Réponses: 2
    Dernier message: 13/03/2003, 20h50

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