2011-06-18 11 views
191

¿Cómo puedo detectar si mi archivo Node.JS fue llamado usando SH: node path-to-file o JS: require('path-to-file')?Node.JS: detectar si se requiere o directamente a través de la línea de comandos

Ésta es la Node.JS equivalentes a mi pregunta anterior en Perl: How can I run my Perl script only if it wasn't loaded with require?

+1

Posible duplicado de [node.js equivalente de python si \ _ \ _ name \ _ \ _ == '\ _ \ _ main \ _ \ _'] (http://stackoverflow.com/questions/4981891/node-js-equivalent-of-pythons-if-name-main) – GingerPlusPlus

Respuesta

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

Ver documentación para esta aquí: https://nodejs.org/docs/latest/api/all.html#modules_accessing_the_main_module

+0

gracias Nicolas (y Jesse) –

+2

¿Hay alguna forma de evitar esto? Tengo un código (que no tengo control) que hace esto, pero necesito requerir() y hacer que actúe como si hubiera sido llamado directamente. Básicamente, necesito engañar a algo que usa esa prueba para pensar que fue llamado directamente. – Kevin

+2

@Kevin No sé cómo hacer esto con 'require()', pero podrías hacerlo importando el archivo y ejecutando 'eval' en él, o ejecutando' require ('child_process'). Exec ('node the_file.js') ' – MalcolmOcean

58

Hay otra manera un poco más corto (no se indica en el mencionado documentos).

var runningAsScript = !module.parent;

que he descrito más detalles acerca de cómo funciona todo esto bajo el capó en this blog post.

+0

+1, me gusta más, pero lo dudaré antes de cambiar las respuestas aceptadas. :) –

+8

Como indiqué, la forma oficial que está documentada es la que se indica en @nicolaskruchten. Esta es solo una alternativa, no es necesario cambiar la respuesta aceptada. Ambos trabajan. –

+1

Tuve que usar esto en lugar de la manera documentada, la forma documentada funciona para, por ejemplo, 'node script.js' pero no' cat script.js | nodo'. De esta manera funciona para ambos. –

2

Estaba un poco confundido por la terminología utilizada en la (s) explicación (es). Así que tuve que hacer un par de pruebas rápidas.

he encontrado que estos producen los mismos resultados:

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

Y para las otras personas confundidas (y para responder a la pregunta directa):

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

Al igual que en Python, siempre encuentro tratando de recordar cómo escribir este maldito fragmento de código. Entonces decidí crear un módulo simple para eso. Me tomó un poco desarrollar ya que acceder a la información del módulo del llamante no es directo, pero fue divertido ver cómo se podía hacer.

Así que la idea es llamar a un módulo y preguntar si el módulo de la persona que llama es el principal. Tenemos que descubrir el módulo de la función de llamada. Mi primer enfoque fue una variación de la respuesta aceptada:

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

Pero eso no está garantizado para funcionar. module.parent apunta al módulo que cargó en la memoria, no en el que nos está llamando. Si fue el módulo de llamadas que cargó este módulo auxiliar en la memoria, está bien. Pero si no fue así, estamos indefensos. Entonces tenemos que intentar algo más. Mi solución fue generar un seguimiento de pila y obtener el nombre del módulo de la persona que llama desde allí:

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; 
}; 

Ahora podemos hacer:

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

O más legible:

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

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

imposible de olvidar :-)

+0

Muy bueno. Me encanta cuando los fragmentos de código comunes se abrevian con un solo nombre. Pequeño ajuste: 'return require.main/* esto no está definido si comenzamos el nodo de forma interactiva */&& require.main.filename === callerModuleName;' – masterxilo

Cuestiones relacionadas