Exécuter la fonction dans le script à partir de la ligne de commande (Node JS)

205

J'écris une application web dans Node. Si j'ai un fichier JS db.jsavec une fonction init, comment pourrais-je appeler cette fonction à partir de la ligne de commande?

winhowes
la source
utilisez npm run-func stackoverflow.com/a/43598047/696535
Pawel
3
@Pawel Je préfère la réponse acceptée car elle ne nécessite pas l'installation d'une dépendance tierce qui peut perdre son support ou contenir des vulnérabilités. C'est un risque que vous courez avec n'importe quelle dépendance, donc limiter les dépendances à celles bien contrôlées et maintenues est toujours une bonne idée.
winhowes
Vous pouvez également utiliser le package npmjs.com/package/invoke-script
Stefan van de Vooren

Réponses:

330

Aucun commentaire sur la raison pour laquelle vous voulez faire cela, ou ce qui pourrait être une pratique plus standard: voici une solution à votre question .... Gardez à l'esprit que le type de guillemets requis par votre ligne de commande peut varier.

Dans votre db.js, exportez la initfonction. Il existe de nombreuses façons, mais par exemple:

module.exports.init = function () {
  console.log('hi');
};

Ensuite, appelez-le comme ceci, en supposant que votre se db.jstrouve dans le même répertoire que votre invite de commande:

node -e 'require("./db").init()'

Pour les autres lecteurs, la initfonction du PO aurait pu s'appeler n'importe quoi, ce n'est pas important, c'est juste le nom spécifique utilisé dans la question.

LeeGee
la source
80
C'était une astuce utile pour tester du javascript qui s'exécutait à partir d'AWS lambda - merci
Alex Hinton
14
Que se passe-t-il si la fonction est asynchrone?
Augustin Riedinger du
24
Dans le cas où quelqu'un d'autre essaie de le faire dans leur package.json en tant que script npm, je l'ai essayé avec les guillemets simples et les guillemets doubles à l'intérieur, mais cela n'a fonctionné que lorsque je les ai commutés: "start": "node - e \ "require ('./ server') () \" ",
Sako73
2
Merci @winhowes pour votre réponse, je viens d'utiliser votre exemple module.exports.init = function () { console.log('hi'); };et node -e 'require("./db").init()'n'a pas fonctionné pour moi en quelque sorte. Je ne suis pas sûr de ce que j'ai fait de mal, mais en suivant votre idée, j'ai utilisé module.exports = myFunction, , puis node -e 'require("./myFunction")()'travaillé pour moi.
C.Lee
3
comme une augmentation de @ commentaire de AlexHinton, j'utilise maintenant ce qui suit pour mimer un événement et le rappel: node -e 'require("./index").handler(require("./fixtures/sample_event_01.json"), {}, console.log)'. Le milieu {}serait le contexte, n'hésitez pas à vous ajuster. Aussi console.log est un peu primitif mais un bon début. Bien sûr, vous pouvez également écrire un CLI.js dédié qui à son tour nécessite () est l'index.js / handler comme indiqué dans d'autres commentaires.
Adrian Föder
51

Comme pour les autres réponses, ajoutez ce qui suit à someFile.js

module.exports.someFunction = function () {
  console.log('hi');
};

Vous pouvez ensuite ajouter ce qui suit à package.json

"scripts": {
   "myScript": "node -e 'require(\"./someFile\").someFunction()'"
}

Depuis le terminal, vous pouvez ensuite appeler

npm run myScript

Je trouve cela un moyen beaucoup plus facile de se souvenir des commandes et de les utiliser

Gaz_Edge
la source
Sur ma machine Win10, cette syntaxe fait simplement écho au script (dans un terminal PowerShell ou d'invite de commandes). L'exécuter directement au lieu de via 'npm run' lance un 'jeton inattendu' pointant vers le début du paramètre require. Je n'ai pas encore trouvé comment le faire fonctionner.
CalvinDale
@CalvinDale même ici, sauf que je peux exécuter le script lui-même dans PowerShell très bien.
ferr
3
Sur ma machine (Windows 10), j'ai dû changer les guillemets doubles et simples, comme ceci: "myScript": "node -e \" require ('./ someFile'). SomeFunction () \ "" Sinon, Node il suffit d'imprimer la commande à l'intérieur des guillemets simples mais de ne pas l'évaluer. Peut-être que cela résout les problèmes de @CalvinDale et ferr.
Christoph
4
Et si nous voulons ajouter un argument à l'appel de fonction?
Miguel Stevens
26

Essayez make-runnable .

Dans db.js, ajoutez require('make-runnable');à la fin.

Vous pouvez maintenant:

node db.js init

Tout argument supplémentaire serait passé à la initméthode.

eye_mew
la source
18

Exécuter directement à partir de CLI (global)

Installer

npm i -g run-func

Utilisation c'est à dire exécuter la fonction "init", elle doit être exportée, voir en bas

run-func db.js init

ou

Exécuter à partir du script package.json (local)

Installer

npm i -S run-func

Installer

"scripts": {
   "init": "run-func db.js init"
}

Usage

npm run init

Params

Tous les arguments suivants seront passés en tant que paramètres de fonction init(param1, param2)

run-func db.js init param1 param2

Important

la fonction (dans cet exemple init) doit être exportée dans le fichier qui la contient

module.exports = { init };

ou export ES6

export { init };
Pawel
la source
Je pensais utiliser la suggestion de eye_mew à utiliser make-runnable, mais c'est beaucoup mieux que ça, je pense. Merci.
luis.espinal
@ luis.espinal Je suis content que vous trouviez cela utile. Il y a moins de magie en arrière-plan et pas besoin de modifier les fichiers. À moins qu'une fonction ne soit pas exportée, elle doit l'être, mais cela a un sens logique, tout comme les modules ES6 ordinaires et leur importation / exportation.
Pawel
cela ne fonctionne pas pour moi; $ run-func db.js init bash: run-func: commande introuvable
Patlatus
@Patlatus à utiliser directement depuis CLI sans script dans package.json l'installer globalementnpm i -g run-func
Pawel
@Patlatus en fait, il y avait un bogue qui ne permettait que cela de s'exécuter dans les scripts package.json. J'ai téléchargé une nouvelle version qui le corrige et cela fonctionne aussi dans le monde entier
Pawel
9

manière simple:

disons que vous avez un fichier db.js dans un répertoire helpers de la structure du projet.

allez maintenant dans le répertoire helpers et allez dans la console des nœuds

 helpers $ node

2) nécessite un fichier db.js

> var db = require("./db")

3) appelez votre fonction (dans votre cas, son init ())

> db.init()

J'espère que cela t'aides

Siyaram Malav
la source
7

Si vous mettez db.jsdans un module , vous pouvez demander à partir db_init.jset juste: node db_init.js.

db.js:

module.exports = {
  method1: function () { ... },
  method2: function () { ... }
}

db_init.js:

var db = require('./db');

db.method1();
db.method2();
Dave
la source
7

Celui-ci est sale mais fonctionne :)

J'appellerai la main()fonction de mon script. Auparavant, je mettais simplement les appels à main à la fin du script. Cependant, j'ai ajouté d'autres fonctions et les ai exportées à partir du script (pour utiliser des fonctions dans d'autres parties du code) - mais je ne veux pas exécuter la fonction main () chaque fois que j'importe d'autres fonctions dans d'autres scripts.

J'ai donc fait cela, dans mon script j'ai supprimé l'appel à main (), et à la fin du script j'ai mis cette vérification:

if (process.argv.includes('main')) {
   main();
}

Donc, quand je veux appeler cette fonction en CLI: node src/myScript.js main

À Kra
la source
5

Je fais un IIFE, quelque chose comme ça:

(() => init())();

ce code sera exécuté immédiatement et invoquera la fonction init.

Natan Deitch
la source
2
Mais si vous exécutez: node init.jset que le fichier contient un IIFE, cela fonctionnera. Je pense que je n'ai pas bien compris votre question. Désolé.
Natan Deitch
Obtenez tout cela, mais si le code contient d'autres fonctions, elles peuvent ou non être appelées
winhowes
1
Vous pouvez même le simplifier (init)();si vous le souhaitez :)
Little doe
1

Parfois, vous souhaitez exécuter une fonction via CLI, parfois vous le souhaitez à requirepartir d'un autre module. Voici comment faire les deux.

// file to run
const runMe = () => {}
if (require.main === module) {
  runMe()
} 
module.exports = runMe
Matt K
la source
-2

Simple, dans le fichier javascript testfile.js:

module.exports.test = function () {
   console.log('hi');
};
this.test();

Exécution à l'invite:

node testfile.js
Elton da Nobrega Mascena
la source
4
Bien sûr, cela vous permet d'exécuter un fichier JS. La question d'origine consiste à appeler une fonction spécifique à l'intérieur de ce fichier sans modifier le flux du fichier (dans votre exemple, il testest exécuté à chaque fois, vous devrez donc changer le fichier pour appeler une autre fonction)
winhowes
-3

Si votre fichier contient juste votre fonction, par exemple:

myFile.js:

function myMethod(someVariable) {
    console.log(someVariable)
}

L'appeler à partir de la ligne de commande comme ceci ne se passera pas:

node myFile.js

Mais si vous changez votre fichier:

myFile.js:

myMethod("Hello World");

function myMethod(someVariable) {
    console.log(someVariable)
}

Maintenant, cela fonctionnera à partir de la ligne de commande:

node myFile.js
Blundell
la source
1
Bien sûr, c'est comment exécuter un fichier JS. La question visait plus à savoir si je pouvais exécuter une fonction spécifique (parmi de nombreuses fonctions possibles) où la seule modification concernait l'entrée de ligne de commande plutôt que le fichier JS lui-même par appel de fonction
winhowes
Il ne s'agit pas du scénario demandé par la personne
jobmo
@jobmo c'est, ils veulent exécuter une méthode à partir de la ligne cmd, cela fait cela. (Je suis arrivé ici en recherchant moi-même la question, afin que quelqu'un d'autre puisse apprécier la réponse), ne vous inquiétez pas, il existe un ensemble diversifié de réponses que vous avez le choix
Blundell
Exactement, la question concerne l'exécution d'une méthode à partir de la ligne cmd. Dans cette réponse, myFile.js est exécuté. Il n'exécute aucune fonction. Il arrive alors que le fichier ait une fonction et la fonction est appelée à l'intérieur du fichier. C'était mon point.
jobmo
Vous venez d'expliquer que la réponse exécute la fonction à partir de la ligne de commande: +1:
Blundell