2010-09-15 38 views
4

L'aperçu rapide est la suivante: pour mon application Web, je peux écrire la plupart de mes fonctionnalités en utilisant les vues CouchApp et CouchDB, etc. J'aime la fonctionnalité de CouchApp qui pousse mon code vers le serveur via la réplication. facile. Cependant, pour effectuer un travail arbitraire non supporté par couchdb et contourner quelques limitations, j'ai besoin de mettre une plateforme web devant CouchDB. J'envisage de construire ceci dans node.js parce qu'il utilise JavaScript et je veux continuer la méthode de déploiement facile de pousser le code dans la base de données.Est-ce que node.js peut exécuter des fonctions JavaScript tirées de CouchDB comme le fait CouchApp? Comment?

Voici comment j'imagine que cela fonctionne: - J'écris un serveur web/service dans node.js en utilisant la méthode normale et la commande node pour le démarrer. - ce sevice se connecte à la base de données db et obtient une liste virtuelle et une liste de mappage d'URL. Cette liste est stockée dans redis pour une recherche rapide. Cette liste indique au serveur, lorsqu'il reçoit une requête, en fonction de l'hôte et du chemin, etc., quel gestionnaire doit être exécuté. - le serveur récupère le gestionnaire - qui n'est qu'un document, il peut s'agir d'un document de conception ou d'un document json arbitraire dans couchdb. Et puis exécute ce gestionnaire pour gérer la demande, comme si j'écrivais le gestionnaire dans le cadre du nœud js.

Donc la question est, comment obtenir une structure de données fils qui contient une fonction JavaScript, sous forme de texte, et exécuter cette fonction?

Cela peut sembler évident, mais je viens d'un arrière-plan compilé, donc normalement, il y aurait une étape de compilation ici qui rend cela pratiquement impossible. Donc, ce que je pense est en pseudo code: Var chaîne thecode = getValueForMapKey (handlerFunctionIWant); en quelque sortemagicallyexecute (le code)

Existe-t-il une fonction exec ou run qui fera l'étape d'exécution magique ci-dessus en JavaScript?

+0

Intéressant idée - Code de tirer CouchDB à la volée - vous ne jamais aller de l'avant ? –

+0

J'ai vu des gens le faire avec succès. Avec cette technique, vous pouvez déployer simultanément des mises à niveau CouchDB et Node.js. – JasonSmith

+0

Normalement, si le javascript ne change pas, vous mettez le code dans _attachments/script et le chargez en utilisant ''. Si cela change, vous pouvez créer un document ordinaire (en dehors du document de conception) et le récupérer également avec une balise de script. Pour être dynamique, vous pouvez charger plusieurs fichiers et n'exécuter que celui dont vous avez besoin. Seulement faire ajax, eval, db.get etc si vous devez. –

Répondre

0

eval (handlerFunctionIwant) est l'appel pour l'exécuter. Vous devez vous assurer qu'il n'y a aucun moyen pour les pirates d'injecter du code dans cette chaîne, bien sûr.

Il n'est pas clair pour moi si cela va l'évaluer dans un contexte qui a accès à d'autres ressources javescript, comme le reste de node.js ou l'accès à votre bibliothèque couchdb.

11

Il s'exécutera dans le contexte node.js.

Vous pouvez également l'utiliser dans le nœud, comme celui-ci, en fonction dynamique:

var cradle = require('cradle'); 
var db = new(cradle.Connection)().database('db_name'); 

db.get('_design/node%2Fyour_code', function (err, doc) { 
    if (!err){ 
    var your_code = new Function(doc['arguments'].join(','), doc.code); 
    your_code("cool", "also cool"); 
    }else{ 
    console.error('error:', err); 
    } 
}); 

faire vos documents ressemblent à ceci:

{ 
    "_id": "_design/node/your_code", 
    "arguments": [ 
     "nameOfArg1", 
     "nameOfArg2" 
    ], 
    "code": "console.log('arg1', nameOfArg1); console.log('arg2', nameOfArg2);" 
} 

Il est dans la même portée que lorsque la nouvelle La fonction est appelée, donc vous avez accès au berceau, ou vous pouvez avoir besoin d'autres librairies, qui seront chargées comme si c'était une fonction anon dans cette portée. Mettez-le dans un document de conception, alors seulement admin peut apporter des modifications, hors de la boîte.

Voici une plus belle, mais approche similaire:

// Format, in db: 
doc = { 
    "_id": "_design/node", 
    "your_function_name": { 
     "arguments": [ 
      "nameOfArg1", 
      "nameOfArg2" 
     ], 
     "code": "console.log('arg1', nameOfArg1); console.log('arg2', nameOfArg2);" 
    }, 
    "your_other_function_name": { 
     "arguments": [ 
      "name" 
     ], 
     "code": "console.log('hello', name, 'how\\'s it going, bro?');" 
    } 
}; 


var cradle = require('cradle'); 
var db = new(cradle.Connection)().database('db_name'); 

function run_from_db(name, args){ 
    db.get('_design/node', function (err, doc) { 
    if (!err){ 
     if (doc[name] !== undefined){ 
     var fn = new Function(doc[name]['arguments'].join(','), doc[name].code); 
     fn.apply(fn, args); 
     }else{ 
     console.error("could not find", name, "in _design/node"); 
     } 
    }else{ 
     console.error(err); 
    } 
    }); 
} 


run_from_db('your_other_function_name', ['konsumer']); 

Affichera:

hello konsumer how's it going, bro?