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 :

Closure, scope et ajax


Sujet :

JavaScript

  1. #1
    Futur Membre du Club
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2012
    Messages : 7
    Points : 5
    Points
    5
    Par défaut Closure, scope et ajax
    Bonjour,

    Désolé de vous embêter encore avec ça, mais je n'arrive pas à comprendre pourquoi je ne récupère pas les "bonnes" variables dans mon contexte...

    J'utilise le "plugin" jQuery.ajaxQueue :
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    (function($) {
     
    // jQuery on an empty object, we are going to use this as our Queue
    var ajaxQueue = $({});
     
    $.ajaxQueue = function( ajaxOpts ) {
        var jqXHR,
            dfd = $.Deferred(),
            promise = dfd.promise();
     
        // queue our ajax request
        // Ici, ajaxOpts est bien toujours Ok pour moi
        //(ie, ajaxOpts.url est effectivement bien différent à chaque appel, "url1", "url2","url3', etc)
        ajaxQueue.queue( doRequest );
     
        // add the abort method
        promise.abort = function( statusText ) {
     
            // proxy abort to the jqXHR if it is active
            if ( jqXHR ) {
                return jqXHR.abort( statusText );
            }
     
            // if there wasn't already a jqXHR we need to remove from queue
            var queue = ajaxQueue.queue(),
                index = $.inArray( doRequest, queue );
     
            if ( index > -1 ) {
                queue.splice( index, 1 );
            }
     
            // and then reject the deferred
            dfd.rejectWith( ajaxOpts.context || ajaxOpts, [ promise, statusText, "" ] );
            return promise;
        };
     
        // run the actual query
        /* Par contre, ici, ce n'est plus le cas, ajaxOpts.url est toujours la dernière du tableau (cf.  SCRIPTS_JS plus loin) sauf pour le premier appel (ajaxOpts.url est bien égal à "url1" pour le premier appel, mais pour tous les autres appels, ajaxOpts.url est toujours égal au dernier élément du tableau)
        function doRequest( next ) {
            jqXHR = $.ajax( ajaxOpts )
                .done( dfd.resolve )
                .fail( dfd.reject )
                .then( next, next );
        }
     
        return promise;
    };
     
    })(jQuery);
    Tout fonctionne comme attendu, sauf si j'appelle $.ajaxQueue dans le cadre d'une boucle, ie (code simplifié) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    var SCRIPTS_JS = new Array(
    url1,url2,url3,...
    )
     
    for (var i=0;i<SCRIPTS_JS.length;i++) {
    	jQuery.extend(
    		optsAjax, // défini par ailleurs
    		{
    			url: SCRIPTS_JS[i]
    		}
    	);
    	$.ajaxQueue(optsAjax); // Lors de cet appel, optsAjax correspond bien toujours à ce qui est attendu (ie: l'url est bien la courante dans la boucle
    }
    En fait je ne comprends pas où je "perds" le fil au niveau de $.ajaxQueue puisqu'il semble que la closure supérieure est correcte lors de l'appel initial mais plus correcte lors de l'exécution de "function doRequest( next )".

    C'est sans aucun doute (encore ) un problème de scope/closure, etc, et j'ai bien essayé d'implémenter les solutions données par ailleurs (fonctions anonyme, etc), mais je dois surement très mal m'y prendre...

    Par exemple, j'ai essayé ça pour "contraindre" les variables dans la boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    for (var i=0;i<SCRIPTS_JS.length;i++) {
    	(function () {
    		jQuery.extend(
    			optsAjax, // défini par ailleurs
    			{
    				url: JSSCRIPTS_URL + SCRIPTS_JS[i]
    			}
    		);
    		$.ajaxQueue(optsAjax); // Lors de cet appel, optsAjax correspond bien toujours à ce qui est attendu (ie: l'url est bien la courante dans la boucle
    	}())
    }
    Je sais que ce sujet a été abordé maintes fois sur ce forum (notamment ici http://www.developpez.net/forums/d13...ion-dynamique/) et par ailleurs, mais j'ai vainement essayé toutes les solutions trouvées...

    Merci d'avance pour votre patience et vos éventuelles pistes de résolution.

    Bonne journée

    PS : Dans le cadre de plusieurs appels hors bloucle, tout fonctionne comme attendu, ie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    $.ajaxQueue({url:url1});
    $.ajaxQueue({url:url2});
    $.ajaxQueue({url:url3});
    ...
    Donc tout laisse à penser que c'est au niveau de l'appel de $.ajaxQueue(...) dans la boucle qu'il faudrait agir, mais où et comment ?

    Merci encore

  2. #2
    Futur Membre du Club
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2012
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Je pense avoir trouver une réponse à l'aide de jQuery.each... L'appel devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    jQuery.each(SCRIPTS_JS, function() {
    	_self=this; // utilise pour référencer les éléments de l'objet en cours pour les fonctions de callback (voir "success" ci-dessous)
    	jQuery.extend(
    		optsAjax, // défini par ailleurs
    		{
    			url: this, // "this" est encore l'objet "each" en cours ici ; ou "_self" ;)
    			success: function () {
    				// Attention "this" n'est plus un objet renvoyé par "each" à ce point (c'est un objet jqXHR), donc il faut utiliser la variable "_self" 
    				console.log('url : ' + _self);
    		}
    	);
    	$.ajaxQueue(optsAjax); // Cette fois le contexte est bien préservé
    });
    Donc "each" fait le boulot pour "isoler" les variables en cours, mais la question reste posée pour le cas où on utiliserait pas jQuery...

    Si quelqu'un à un exemple à donner hors utilisation de "each", je suis preneur

    Merci et bonne journée

  3. #3
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Bonjour,

    Ce que tu as loupé dans le topic précédent, c'est que ma solution implique de passer la variable que tu souhaites isoler en argument de la fonction anonyme (ici ton itérateur i)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    for (var i=0;i<SCRIPTS_JS.length;i++) {
    	(function (_i) {
    		jQuery.extend(
    			optsAjax, // défini par ailleurs
    			{
    				url: JSSCRIPTS_URL + SCRIPTS_JS[_i]
    			}
    		);
    		$.ajaxQueue(optsAjax); // Lors de cet appel, optsAjax correspond bien toujours à ce qui est attendu (ie: l'url est bien la courante dans la boucle
    	}(i))
    }
    Ce que fait $.each en passant en argument les éléments un par un à la fonction.
    One Web to rule them all

  4. #4
    Futur Membre du Club
    Femme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2012
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Bonjour,

    Argh, effectivement, tu as 1000 fois raison... J'avais aussi essayé de passer l'élément du tableau à la fonction anonyme, mais pas l'itérateur seul, ie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    for (var i=0;i<SCRIPTS_JS.length;i++) {
    	(function (elem) {
    		jQuery.extend(
    			optsAjax, // défini par ailleurs
    			{
    				url: JSSCRIPTS_URL + elem
    			}
    		);
    		$.ajaxQueue(optsAjax); // Lors de cet appel, optsAjax correspond bien toujours à ce qui est attendu (ie: l'url est bien la courante dans la boucle
    	}(SCRIPTS_JS[i]))
    }
    Merci pour cette précision et bonne journée

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

Discussions similaires

  1. Scope des closures et methodMissing
    Par lionrouge dans le forum Groovy
    Réponses: 0
    Dernier message: 24/02/2014, 08h48
  2. Gestion des managed beans (scope, ajax etc.)
    Par Malone dans le forum JSF
    Réponses: 4
    Dernier message: 26/06/2009, 16h30
  3. [C#] Syntaxe et scope d'un FOR !?
    Par Wavyx dans le forum Windows Forms
    Réponses: 14
    Dernier message: 09/09/2004, 13h07
  4. [C++]closure + héritage + transtypage
    Par JEG dans le forum C++Builder
    Réponses: 11
    Dernier message: 30/01/2004, 14h26

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