javascript - tools - visual studio node js tutorial
Detección del entorno: node.js o navegador (4)
Dado que aparentemente Node.js podría tener ambos (w / NW.js?), Mi forma personal de hacerlo es detectando si la entrada del node
existe en el objeto process.versions
.
var isNode = false;
if (typeof process === ''object'') {
if (typeof process.versions === ''object'') {
if (typeof process.versions.node !== ''undefined'') {
isNode = true;
}
}
}
El multinivel de condiciones es para evitar errores al buscar en una variable indefinida debido a algunas limitaciones de navegadores.
Referencia: https://nodejs.org/api/process.html#process_process_versions
Estoy desarrollando una aplicación JS que necesita funcionar tanto del lado del cliente como del servidor (en Javascript en un navegador y en Node.js), y me gustaría poder reutilizar las partes del código que están utilizado para ambos lados.
Descubrí que la window
era una variable solo accesible en los navegadores y global
en el nodo, por lo que puedo detectar en qué entorno se está ejecutando el código (suponiendo que ningún script declara la variable de la window
)
Son dos problemas.
¿Cómo debo detectar en qué navegador se está ejecutando el código? Por ejemplo, este código está OK. (Este código está en línea, lo que significa que está rodeado por algún código global, reutilizado para ambos entornos)
if window? totalPath= "../examples/#{path}" else totalPath= "../../examples/#{path}"
¿Cómo puedo usar variables globales para ambos entornos? Ahora, estoy haciendo lo siguiente, pero esto realmente no se siente bien.
if window? window.DocUtils = {} window.docX = [] window.docXData= [] else global.DocUtils= {} global.docX = [] global.docXData = []
Hay un paquete npm solo para esto y se puede usar tanto en el lado del cliente como en el lado del servidor.
Puedes usarlo de esta manera
if (isBrowser) {
// do browser only stuff
}
if (isNode) {
// do node.js only stuff
}
Descargo de responsabilidad: soy el autor de este paquete :)
Puede adjuntar a ventana variable o global, según la situación. Aunque no es una forma recomendada de hacer aplicaciones multiplataforma JS:
var app = window ? window : global;
Es mucho mejor tener su variable global, que se utilizará sobre la lógica de la aplicación, pero estará compuesta de partes de diferentes plataformas. Algo como:
var app = {
env: '''',
agent: ''''
};
if (window) {
app.env = ''browser'';
app.agent = navigator.userAgent;
} else if (process) {
app.env = ''node'';
}
Entonces, la idea es que la lógica de la aplicación principal será absolutamente la misma y usará el mismo objeto, solo que el objeto global debe ser modificado en función del entorno. Eso hace que su aplicación sea mucho más portátil y flexible en términos de plataformas.
NOTA: Esta pregunta tenía dos partes, pero como el título era "Detección del entorno: node.js o navegador", primero llegaré a esta parte, porque supongo que muchas personas vienen aquí a buscar una respuesta. Una pregunta separada podría estar en orden.
En JavaScript las variables pueden ser redefinidas por los ámbitos internos, asumiendo que el entorno no ha creado variables denominadas como proceso, global o ventana podría fallar fácilmente, por ejemplo, si uno está utilizando node.js jsdom module, el ejemplo de uso de API tiene
var window = doc.defaultView;
Después de lo cual, cualquier módulo que se ejecute bajo ese alcance fallará sistemáticamente al detectar el entorno en función de la existencia de la variable de window
. Con la misma lógica, cualquier código basado en navegador podría sobreescribir global
o process
, ya que no son variables reservadas en ese entorno.
Afortunadamente, hay una manera de exigir el alcance global y probar qué es: si crea una nueva función utilizando un new Function()
constructor new Function()
, el alcance de ejecución de this
se vincula al alcance global y puede comparar el alcance global directamente a el valor esperado. *)
Entonces, para crear una función verificar si el alcance global es "ventana" sería
var isBrowser=new Function("try {return this===window;}catch(e){ return false;}");
// tests if global scope is binded to window
if(isBrowser()) console.log("running under browser");
Y funcionar para probar si el sope global está ligado a "global" sería
var isNode=new Function("try {return this===global;}catch(e){return false;}");
// tests if global scope is binded to "global"
if(isNode()) console.log("running under node.js");
el try ... catch-part se asegurará de que si la variable no está definida, se devuelve false
.
El isNode()
también podría comparar this.process.title==="node"
o alguna otra variable de ámbito global encontrada dentro de node.js, si así lo desea, pero la comparación con el global debería ser suficiente en la práctica.
NOTA : no se recomienda detectar el entorno en funcionamiento. Sin embargo, puede ser útil en un entorno específico, como un entorno de desarrollo y prueba que tenga algunas características conocidas para el alcance global.
Ahora - la segunda parte de la respuesta. después de que se haya realizado la detección del entorno, puede seleccionar qué estrategia basada en el entorno desea usar (si corresponde) para vincular su variable, que es "global" para su aplicación.
La estrategia recomendada aquí, en mi opinión, sería usar un patrón singleton para vincular tus configuraciones dentro de una clase. Ya hay una buena lista de alternativas en SO
¿Forma más simple / más limpia de implementar singleton en JavaScript?
Por lo tanto, puede ocurrir que si no necesita una variable "global" y no necesita la detección del entorno, simplemente use el patrón singleton para definir un módulo, que almacenará los valores por usted. Bien, uno puede argumentar que el módulo en sí es una variable global, que en realidad es JavaScript, pero al menos en teoría parece una forma un poco más limpia de hacerlo.
*) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function
Nota: Las funciones creadas con el constructor de funciones no crean cierres en sus contextos de creación; siempre se crean en el ámbito global. Al ejecutarlos, solo podrán acceder a sus propias variables locales y globales, no a las del alcance en el que se llamó al constructor de la función.