2011-06-18 6 views
191

Come posso rilevare se il mio file Node.JS è stato chiamato utilizzando SH: node path-to-file o JS: require('path-to-file')?Node.JS: Rileva se richiesto tramite richiesta o direttamente dalla riga di comando

questo è il Node.JS equivalenti alla mia precedente interrogazione in Perl: How can I run my Perl script only if it wasn't loaded with require?

+1

Possibile duplicato di [node.js equivalente di python se \ _ \ _ nome \ _ \ _== '\ _ \ _ principale \ _ \ _'] (http://stackoverflow.com/questions/4981891/node-js-equivalent-of-pythons-if-name-main) – GingerPlusPlus

risposta

297
if (require.main === module) { 
    console.log('called directly'); 
} else { 
    console.log('required as a module'); 
} 

vedere la documentazione per questo qui: https://nodejs.org/docs/latest/api/all.html#modules_accessing_the_main_module

+0

grazie Nicolas (e Jesse) –

+2

C'è un modo per aggirare questo? Ho il codice (di cui non ho il controllo) che lo fa, ma ho bisogno di richiederlo() e farlo agire come se fosse chiamato direttamente. Fondamentalmente, ho bisogno di prendere in giro qualcosa che usa quel test per pensare che sia stato chiamato direttamente. – Kevin

+2

@Kevin Non lo so fare con 'require()', ma potresti farlo con importare il file eseguendo 'eval' su di esso, o eseguendo' require ('child_process'). Exec ('node the_file.js') ' – MalcolmOcean

58

C'è un altro modo leggermente più corto (non indicato nel citato docs).

var runningAsScript = !module.parent;

ho delineato ulteriori dettagli su come questo tutte le opere sotto il cofano in this blog post.

+0

+1, mi piace di più, ma esiterò prima di passare alle risposte accettate. :) –

+8

Come ho indicato, il modo ufficiale che è documentato è quello illustrato da @nicolaskruchten. Questa è solo un'alternativa, non c'è bisogno di cambiare risposta accettata. Entrambi funzionano. –

+1

Ho dovuto usare questo piuttosto che il modo documentato - il modo documentato funziona per es. 'node script.js' ma non' cat script.js | node'. In questo modo funziona per entrambi. –

2

Ero un po 'confuso dalla terminologia utilizzata nella spiegazione (s). Quindi ho dovuto fare un paio di test rapidi.

ho scoperto che questi producono gli stessi risultati:

var isCLI = !module.parent; 
var isCLI = require.main === module; 

E per le altre persone confuse (e per rispondere alla domanda direttamente):

var isCLI = require.main === module; 
var wasRequired = !isCLI; 
1

Proprio come in Python, ho sempre trovato sto cercando di ricordare come scrivere questo dannato frammento di codice. Così ho deciso di creare un modulo semplice per questo. Mi ci è voluto un po 'di tempo per sviluppare l'accesso alle informazioni sul modulo del chiamante, ma è stato divertente vedere come sarebbe stato possibile.

Quindi l'idea è di chiamare un modulo e chiedere se il modulo chiamante è quello principale. Dobbiamo capire il modulo della funzione chiamante. Il mio primo approccio era una variazione della risposta accettata:

module.exports = function() { 
    return require.main === module.parent; 
}; 

Ma non è garantito che funzioni. module.parent punti al modulo che ha caricato in memoria, non quello che ci chiama. Se era il modulo chiamante che ha caricato questo modulo helper in memoria, va bene. Ma se non lo fosse, siamo indifesi. Quindi dobbiamo provare qualcos'altro. La mia soluzione era di generare una traccia dello stack e ottenere il nome del modulo del chiamante da lì:

module.exports = function() { 
    // generate a stack trace 
    const stack = (new Error()).stack; 
    // the third line refers to our caller 
    const stackLine = stack.split("\n")[2]; 
    // extract the module name from that line 
    const callerModuleName = /\((.*):\d+:\d+\)$/.exec(stackLine)[1]; 

    return require.main.filename === callerModuleName; 
}; 

Ora possiamo fare:

if (require("./is-main-module")()) { // notice the `()` at the end 
    // do something 
} else { 
    // do something else 
} 

O più leggibile:

const isMainModule = require("./is-main-module"); 

if (isMainModule()) { 
    // do something 
} else { 
    // do something else 
} 

impossibile da dimenticare :-)

+0

Molto interessante. Mi piace quando i frammenti di codice comuni sono abbreviati in un singolo nome. Piccola regolazione: 'return require.main/* non è definito se abbiamo avviato il nodo in modo interattivo */&& require.main.filename === callerModuleName;' – masterxilo

Problemi correlati