2010-12-15 149 views
1

J'ai cette classe js qui a une fonction anonyme pour récupérer des résultats de requête. Étant donné que la fonction qui gère les résultats est anonyme, je ne peux pas enregistrer les résultats dans une variable this.var et les utiliser ailleurs car cela dans la référence anonyme à l'objet window. Je ne peux pas le retourner en tant que fonction de retour non plus alors comment puis-je faire avec ces résultats pour les avoir disponibles ailleurs?Javascript fonction anonyme question

someObject = { 
    // this.db is created, no need to paste that code 
    dbGetAnimals: function() { 
     this.db.readTransaction(function(tx) { 
      tx.executeSql("SELECT * FROM animals", function(tx, results){ 
       return results; 
      }) 
     }); 
    }, 
    printAllAnimals: function() { 
     var animals = this.dbGetAnimals(); 
     alert (animals);// undefined 
    } 
} 

someObject.printAllAnimals(); 
+1

dooooont envoyer sql à partir d'un appel javascript, qui vous ouvre à beaucoup d'attaques. –

+0

compagnon de stockage Web. apprendre avant de poster lol: http: //www.html5rocks.com/tutorials/webdatabase/todo/? todo = sddf –

Répondre

3

Vous pouvez créer une variable locale pour tenir votre référence this. Votre fonction anonyme deviendra une fermeture, donc elle sera capable de voir cette variable locale.

dbGetAnimals: function() { 
    var myself = this; 
    this.db.readTransaction(function(tx) { 
     tx.executeSql("SELECT * FROM animals", function(tx, results){ 
      myself.var = results; 
     }) 
    }); 
}, 
+2

C'est la façon la plus simple de le faire. Mais je pense que c'est moche. Si j'ai besoin d'un rappel pour s'exécuter dans un contexte, je viens de lier le contexte en utilisant un lib. Si vous n'utilisez pas de lib, c'est la voie à suivre. Voir http://www.prototypejs.org/api/function/bind pour une description complète du problème –

0

Cela se produit parce que la fonction anonyme executeSql est une fonction de rappel qui n'est pas exécutée jusqu'à ce que les compmetes de la requête, qui, par définition, être après dbGetAnimals retours. C'est pourquoi votre appel à dbGetAnimals renvoie undefined.

Vous devrez passer une fonction de rappel pour recevoir les Resutls de requête à partir du rappel executSql:

someObject = { 
    // this.db is created, no need to paste that code 
    dbGetAnimals: function (callback) { 
     this.db.readTransaction(function(tx) { 
      tx.executeSql("SELECT * FROM animals", function(tx, results){ 
       callback(results); 
      }); 
     }); 
    }, 
    printAllAnimals: function() { 
     this.dbGetAnimals(function(animals) { 
      alert(animals) 
     }); 
    } 
} 


someObject.printAllAnimals(); 
+0

Je reçois: Uncaught ReferenceError: les animaux ne sont pas définis –

+0

@Tim: Oh duh. Ce code avait le même problème que vous - le 'alert()' s'exécuterait avant que la requête ne soit réellement exécutée. J'ai corrigé le code ci-dessus. – josh3736

+0

ok mais cela ne sauve toujours pas mon problème. Bien que la fonction alert() puisse fonctionner à l'intérieur de cette fonction de rappel, je n'ai aucun moyen de rendre les «animaux» disponibles pour le reste de la classe. Comment faire pour que 'printAllAnimals', lorsqu'il est appelé, renvoie les 'animaux' à l'intérieur de l'objet lui-même? –

2

Vous essayez de faire synchrone/programmation non-bloquant traditionnel où vous voulez faire asynchrone la programmation.

var someObject = function()({ 
    this.dbGetAnimals = function (callback) { 
     db.readTransaction(function(tx) { 
      tx.executeSql("SELECT * FROM animals", function(tx, results){ 
       callback(results); 
      }) 
     }); 
    }, 

    this.printAllAnimals = function (callback) { 
     this.dbGetAnimals(callback); 
    } 
})(); 

someObject.printAllAnimals(function(animals) { 
    alert(animals); 
} 

Il y a des façons beaucoup plus propres à le faire, mais pour la programmation async vous devez apprendre à tout faire sur place callbacks des retours directs.

+0

Je vais vous expliquer ma situation pour voir pourquoi c'est un gros problème. Je construis une petite application ExtJs avec une grille à l'intérieur. Donc d'abord j'ai une fenêtre ExtJS puis j'ajoute un Grid à cette fenêtre. La grille nécessite les éléments pour afficher quelque chose. Avec ce type de requêtes et de callbacks, il est impossible de simplement retourner les valeurs de la grille pour les utiliser. Je dois créer la transaction et dans la transaction construire la fenêtre et la grille. Dans votre exemple, les 'animaux' sont toujours piégés dans la fonction de rappel de 'printAllAnimals'. J'ai créé un exemple complet sur http://pastebin.com/3a8GQG8F. –

+0

Vous pouvez insérer cela dans une page HTML et regarder pour le stockage local en utilisant les outils de développement chrome. Comme vous pouvez le voir dans l'exemple, alert (animals) renvoie undefined tout le temps, alors comment faire pour utiliser ce résultat en dehors de la fonction callback? –