Clases de Node.js ES6 con require

103

Entonces, hasta ahora, he creado clases y módulos de node.jsla siguiente manera:

    var fs = require('fs');

var animalModule = (function () {
    /**
     * Constructor initialize object
     * @constructor
     */
    var Animal = function (name) {
        this.name = name;
    };

    Animal.prototype.print = function () {
        console.log('Name is :'+ this.name);
    };

    return {
        Animal: Animal
    }
}());

module.exports = animalModule;

Ahora, con ES6, puede crear clases "reales" como esta:

class Animal{

 constructor(name){
    this.name = name ;
 }

 print(){
    console.log('Name is :'+ this.name);
 }
}

Ahora, en primer lugar, me encanta esto :) pero plantea una pregunta. ¿Cómo se usa esto combinado con node.jsla estructura del módulo de '?

Supongamos que tiene una clase en la que desea utilizar un módulo por motivos de demostración, digamos que desea utilizar fs

para que crees tu archivo:


Animal.js

var fs = require('fs');
class Animal{

 constructor(name){
    this.name = name ;
 }

 print(){
    console.log('Name is :'+ this.name);
 }
}

¿Sería esta la forma correcta?

Además, ¿cómo expones esta clase a otros archivos dentro de mi proyecto de nodo? ¿Y aún podría extender esta clase si la usa en un archivo separado?

Espero que algunos de ustedes puedan responder estas preguntas :)

Marc Rasmussen
fuente
3
Simplemente trate el nombre de la clase ES6 de la misma manera que hubiera tratado el nombre del constructor en la forma ES5. Son uno y lo mismo. La sintaxis de ES6 es simplemente azúcar sintáctica y crea exactamente el mismo prototipo subyacente, función de constructor y objetos.
jfriend00
Ese IIFE que crea su no animalModuletiene sentido en un módulo de nodo que tiene su propio alcance de módulo de todos modos.
Bergi

Respuestas:

156

Sí, tu ejemplo funcionaría bien.

En cuanto a exponer sus clases, puede exportuna clase como cualquier otra cosa:

class Animal {...}
module.exports = Animal;

O el más corto:

module.exports = class Animal {

};

Una vez importado a otro módulo, puede tratarlo como si estuviera definido en ese archivo:

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

class Cat extends Animal {
    ...
}
rossipedia
fuente
8
También puede hacer algo como module.exports = class Animal {}
Paul
eso es cierto, sigo olvidando que puedes nombrar cosas durante la asignación.
rossipedia
Todo se reduce al estilo y la claridad del código. module.exportsse utiliza normalmente para una exportación anónima, mientras que exportse utiliza para una exportación con nombre. Esta es una cortesía de codificación básica (podría decirse), que puede ayudar a otros a saber cómo importar su clase, módulo, etcétera.
greg.arnott
7
module.exports = Animal;sería la respuesta o el equivalente más directo a la pregunta y es válido junto con el const Animal = require('./animal');código de llamada. ¿Puede actualizar su respuesta para incluirla?
dom
1
Gracias amigo, he estado luchando para que las importaciones de clases funcionen correctamente durante 2 horas.
kiwicomb123
11

Simplemente trate el nombre de la clase ES6 de la misma manera que hubiera tratado el nombre del constructor en la forma ES5. Son uno y lo mismo.

La sintaxis de ES6 es simplemente azúcar sintáctica y crea exactamente el mismo prototipo subyacente, función de constructor y objetos.

Entonces, en su ejemplo de ES6 con:

// animal.js
class Animal {
    ...
}

var a = new Animal();

module.exports = {Animal: Animal};

Puede tratarlo Animalcomo el constructor de su objeto (lo mismo que lo hubiera hecho en ES5). Puede exportar el constructor. Puede llamar al constructor con new Animal(). Todo es igual para usarlo. Solo la sintaxis de la declaración es diferente. Incluso todavía hay un Animal.prototypeque tiene todos tus métodos. La forma ES6 realmente crea el mismo resultado de codificación, solo que con una sintaxis más elegante / agradable.


En el lado de la importación, esto se usaría así:

const Animal = require('./animal.js').Animal;

let a = new Animal();

Este esquema exporta el constructor Animal como la .Animalpropiedad que le permite exportar más de una cosa de ese módulo.

Si no necesita exportar más de una cosa, puede hacer esto:

// animal.js
class Animal {
    ...
}

module.exports = Animal;

Y luego importarlo con:

const Animal = require('./animal.js');

let a = new Animal();
jfriend00
fuente
No sé por qué, pero esto simplemente no funcionó para mí. module.exports = Animales la única solución que funciona.
Sam
1
@Sam: lo que muestra mi exportación necesita algo diferente require()de lo que muestra su exportación, por lo que sería por eso que uno funcionaría y el otro no. Debe hacer coincidir cómo funciona la importación con cómo se define la exportación. Más detalles para explicar esto se agregaron a mi respuesta.
jfriend00
6

La forma de ES6 de require es import. Puede exportsu clase e importarla en otro lugar usando la import { ClassName } from 'path/to/ClassName'sintaxis.

import fs from 'fs';
export default class Animal {

  constructor(name){
    this.name = name ;
  }

  print(){
    console.log('Name is :'+ this.name);
  }
}

import Animal from 'path/to/Animal.js';
Fan Jin
fuente
4
Sería bueno aclarar que esta es una opción, pero no un requisito. Esta es la sintaxis del módulo ES6, pero aún puede usar una clase ES6 con las exportaciones CommonJS normales de Node. No es necesario utilizar la sintaxis de exportación de ES6 con las clases. Llamarlo The ES6 wayes algo engañoso.
loganfsmyth
2
Eso es cierto, es una preferencia personal. Personalmente, usaría importover requiresolo por el bien de la coherencia de sintaxis.
Fan Jin
2
Sí, es un enfoque sólido y yo también lo hago, solo tenga en cuenta que la forma en que Babel importinteropera con los módulos CommonJS no es probable que termine funcionando en Node, por lo que podría requerir cambios de código en el futuro para ser compatible con Node sin Babel. .
loganfsmyth
4
Los módulos ES6 (importación y exportación) aún son experimentales en el nodo 10 y deben
activarse
Para agregar al punto de @dorking. El nodo 10.15.3 es la versión LTS (soporte a largo plazo) y estará disponible hasta abril de 2020. Detalles adicionales aquí: nodejs.org/en/about/releases
gtzilla
1

Usando clases en el nodo -

Aquí estamos solicitando el módulo ReadWrite y llamando a makeObject (), que devuelve el objeto de la clase ReadWrite. Que estamos usando para llamar a los métodos. index.js

const ReadWrite = require('./ReadWrite').makeObject();
const express = require('express');
const app = express();

class Start {
  constructor() {
    const server = app.listen(8081),
     host = server.address().address,
     port = server.address().port
    console.log("Example app listening at http://%s:%s", host, port);
    console.log('Running');

  }

  async route(req, res, next) {
    const result = await ReadWrite.readWrite();
    res.send(result);
  }
}

const obj1 = new Start();
app.get('/', obj1.route);
module.exports = Start;

ReadWrite.js

Aquí hacemos un método makeObject, que asegura que se devuelva un objeto, solo si un objeto no está disponible.

class ReadWrite {
    constructor() {
        console.log('Read Write'); 
        this.x;   
    }
    static makeObject() {        
        if (!this.x) {
            this.x = new ReadWrite();
        }
        return this.x;
    }
    read(){
    return "read"
    }

    write(){
        return "write"
    }


    async readWrite() {
        try {
            const obj = ReadWrite.makeObject();
            const result = await Promise.all([ obj.read(), obj.write()])
            console.log(result);
            check();
            return result
        }
        catch(err) {
            console.log(err);

        }
    }
}
module.exports = ReadWrite;

Para obtener más explicaciones, vaya a https://medium.com/@nynptel/node-js-boiler-plate-code-using-singleton-classes-5b479e513f74

Nayan Patel
fuente
0

En el archivo de clase, puede usar:

module.exports = class ClassNameHere {
 print() {
  console.log('In print function');
 }
}

o puedes usar esta sintaxis

class ClassNameHere{
 print(){
  console.log('In print function');
 }
}

module.exports = ClassNameHere;

Por otro lado, para usar esta clase en cualquier otro archivo, debe seguir estos pasos. Primero requiere ese archivo usando esta sintaxis: const anyVariableNameHere = require('filePathHere');

Luego crea un objeto const classObject = new anyVariableNameHere();

Después de esto, puede usar classObjectpara acceder a las variables de clase reales

Burhan Maseel
fuente