2010-11-04 9 views
0

J'ai le morceau de javascript suivant mais pour une raison de portée, les "noms" renvoyés par myfunc sont vides.Problème de portée JavaScript

var myfunc = function(client, id) { 
    var names = new Array(); 
    client.query(
    'SELECT stuff FROM mytable WHERE id="'+id+'"', 
    (function selectCb(err, results, fields) { 
     if (err) { 
     throw err; 
     } 
     for (result in results) { 
     // This prints fine 
     console.log(results[result].name); 
     names[result] = results[result].name; 
     } 
     client.end(); 
    }) 
); 
    // The following returns empty 
    return names; 
} 

console.log(myfunc(1,2)); 

Comment puis-je le faire sortir du cadre?

Répondre

1

Il est vide car l'appel à votre fonction "requête" est asynchrone. La fonction que vous transmettez ne sera pas exécutée tant que les résultats ne seront pas disponibles. Par conséquent, votre fonction "myfunc" renvoie immédiatement, bien avant que cette fonction de rappel ne soit invoquée.

L'utilisation de Javascript dans un navigateur, vous devez penser en ces termes. Au lieu d'attendre vos « noms » pour être prêt immédiatement, le changement « myfunc » pour que vous passiez il une fonction de rappel à invoquer lorsque les noms sont actuellement disponibles:

var myfunc = function(client, id, whenFinished) { 
    var names = new Array(); 
    client.query(
    'SELECT stuff FROM mytable WHERE id="'+id+'"', 
    (function selectCb(err, results, fields) { 
     if (err) { 
     throw err; 
     } 
     for (result in results) { 
     // This prints fine 
     console.log(results[result].name); 
     names[result] = results[result].name; 
     } 
     client.end(); 
     if (whenFinished) whenFinished(names); // callback 
    }) 
); 
}; 

Maintenant, lorsque vous appelez votre fonction, au lieu d'attendre les « noms » comme une valeur de retour, vous passerez dans une autre fonction qui agira sur la liste des noms:

myfunc(1, 2, function(names) { console.log(names); }); 
+0

Comment pourrais-je faire ça? –

+0

Je vais ajouter à ma réponse. – Pointy

0
var names = new Array(); 

var myfunc = function(client, id) { 

    client.query(
    'SELECT stuff FROM mytable WHERE id="'+id+'"',function selectCb(err, results, fields) 
    { 
     if (err) { 
     throw err; 
     } 
     for (result in results) { 
     // This prints fine 
     console.log(results[result].name); 
     names[result] = results[result].name; 
     } 
     client.end(); 
    } 
); 
    // The following returns empty 
    return names; 
} 

console.log(myfunc(1,2)); 

essayer de faire des noms globaux

+1

cela ne va pas aider, je ne pense pas. * Eventuellement * le tableau "names" sera rempli, mais pas immédiatement. – Pointy

1

Si client.query (...) est asynchrone, le selectCb fonction ne serait pas courir et noms auraient pas changé par le temps renvoie myfunc. Vous devez redéfinir myfunc pour renvoyer noms de façon asynchrone (en acceptant par exemple un paramètre de fonction qu'il appelle à la fin de selectCb).

+0

Pourriez-vous me donner un exemple concret ou me diriger vers une référence? Merci! –