2011-11-28 1 views
0

J'utilise jQuery depuis quelques années avec une compréhension très limitée du javascript vanilla. Scope, le modèle d'objet, et la plupart des modèles de conception que je vois utilisés dans javascript me déroutent. J'essaie d'implémenter une classe qui sera éventuellement utilisée dans un greffon d'ordonnancement que j'ai besoin d'écrire et j'ai du mal à comprendre pourquoi les données stockées dans l'un des membres de ma classe ne semblent pas disponibles. Je ne suis pas sûr si le problème est avec la portée ou un autre comportement que je ne comprends pas.Pourquoi mon membre de classe de données n'est-il pas directement disponible?

J'ai le code suivant avec 2 questions dans les commentaires aux endroits appropriés. La première question est de savoir si ma solution de contournement de portée dans mon appel getJSON est la façon correcte de gérer le problème de portée dans getJSON. Ma deuxième question est pourquoi je ne peux pas accéder directement à schedule.data.

function Schedule() { 
    this.year = null; 
    this.month = null; 
    this.day = null; 

    this.start_datetime = null; 
    this.start_timestamp = null; 
    this.end_datetime = null; 
    this.end_timestamp = null; 

    this.data = []; 

    return this; 
} 

Schedule.prototype.init = function() { 
    var url = '/tripsys/new_admin/employee_schedule/get_employee_schedule_data/' + this.start_timestamp + '/' + this.end_timestamp; 
    var self = this; // 1. trying to work around scope issues. Is this the correct way to handle the scope problems here? 
    $.getJSON(url, function(data) { 
     self.data = data; 
    }); 
} 

var schedule = new Schedule(); 

$(document).ready(function() { 
    schedule.year = $('#year').text(); 
    schedule.month = $('#month').text(); 
    schedule.day = $('#day').text(); 
    schedule.start_datetime = new Date(schedule.year, schedule.month - 1, schedule.day); 
    schedule.start_timestamp = Math.round(schedule.start_datetime.getTime()/1000); 
    schedule.end_datetime = new Date(schedule.year, schedule.month - 1, schedule.day, 23, 59, 59); 
    schedule.end_timestamp = Math.round(schedule.end_datetime.getTime()/1000); 

    schedule.init(); 
    console.log(schedule); // if I log the whole schedule object the data that I expect to be in the "data" member is there 
    console.log(schedule.data); // 2. why is the data that I expect to be in the "data" member not there when I access schedule.data directly? 
}); 

Nous vous remercions de votre compréhension.

+1

Sur une note de côté, vous devriez vraiment comprendre la langue que vous travaillez avec, surtout après l'avoir utilisé pendant 2 ans. Je suggère de lire un peu sur le sujet. –

+0

Je suis d'accord.Dans le passé, j'ai fait plus de travail de backend et je n'ai jamais eu besoin de faire quoi que ce soit de plus avec javascript que de simples manipulations dom qui jQuery résume vraiment bien. Il est temps de commencer à mieux comprendre le javascript. Merci à tous pour l'aide. –

+0

Ahh, ça a plus de sens. Je suis maintenant en train de m'enseigner la programmation web maintenant, ce qui implique bien entendu l'apprentissage de js. –

Répondre

1

Eh bien le numéro un est correct en ce que vous devez enregistrer la référence this tant que vous pouvez encore parce que lorsque la fonction interne est appelée par jQuery, this à l'intérieur de la fonction fera référence à l'objet ajax.

Dans le deuxième commentaire, vous vous connectez schedule.data avant la fin de la requête ajax. Vous pouvez voir schedule.data lorsque vous vous connectez schedule parce que lorsque vous vous connectez un objet dans Google Chrome, les propriétés de l'objet sont récupérées après que vous "développez" manuellement l'objet dans la console chrome. Lorsque vous le "développez" manuellement, la requête est déjà terminée à ce moment-là.

Vous pouvez reproduire comme ceci:

var a = {}; 
console.log(a); //do not "expand" the object properties yet 
console.log(a.property); //undefined 
a.property = "value"; 
//"expand" the already logged object and it will have "value" 
+0

Oui, j'utilise le chrome et je vois ce que vous voulez dire avec votre exemple d '"ouverture" d'un objet dans la console. Explication parfaite! Merci –

1

Ceci est probablement dû au fait que dans cette ligne schedule.init();, il effectue un appel ajax qui n'est pas encore terminé lorsque vous faites ensuite console.log(schedule.data);. Les appels Ajax sont asynchrones. Les appeler ne fait que commencer l'opération de mise en réseau, puis ils reviennent immédiatement. Ils ne sont pas terminés tant que la fonction de gestionnaire de succès n'a pas été appelée (et que self.data est affectée). Par conséquent, si vous souhaitez consulter les données de l'objet de planification obtenu dans la fonction .init(), vous devez attendre que l'appel ajax soit terminé ou que vous fassiez quelque chose avec les données de la fonction d'achèvement.

1
  1. Oui, cela fonctionnera, bien qu'il ne soit pas une question de portée autant qu'il utilise la portée des variables pour contourner un problème contexte . Pour accéder à schedule.data, vous devez attendre que les données soient arrivées. En d'autres termes, placez le code console.log dans le rappel.

1

Le problème est que l'appel ajax n'est pas retourné avant de vous connecter l'objet. Si vous voulez faire la fonction appel ajax synchrone et la init obtient un résultat avant de vous connecter, utilisez le async param un appel jQuery ajax:

$.ajax({ 
    url: url, 
    dataType: 'json', 
    async: false, 
    success: function(data){ 
     self.data = data; 
     console.log(data); 
    } 
}); 
+0

synchrone asynchrone javascript et xml – Esailija

+1

Note: Faire des appels ajax synchrones verrouiller le navigateur pour la durée de l'opération de mise en réseau. Ce n'est généralement pas le meilleur moyen de coder une application Web. – jfriend00

Questions connexes