Passaggio di argomenti a require (durante il caricamento del modulo)


114

È possibile passare argomenti durante il caricamento di un modulo utilizzando require?

Ho il modulo login.js che fornisce la funzionalità di accesso. Richiede una connessione al database e desidero che la stessa connessione al database venga utilizzata in tutti i miei moduli. Ora esporto una funzione login.setDatabase (...) che mi consente di specificare una connessione al database e funziona perfettamente. Ma preferirei passare il database e qualsiasi altro requisito quando carico il modulo.

var db = ...
var login = require("./login.js")(db);

Sono abbastanza nuovo con NodeJS e di solito sviluppo utilizzando Java e Spring Framework, quindi sì ... questa è un'iniezione di costruttore :) È possibile fare qualcosa come il codice che ho fornito sopra?


Consiglierei anche di guardare le risposte a questa domanda. Come sottolineato nella mia risposta, un idioma comune è passare l' appoggetto ai moduli richiesti.
David Weldon

Invece di fare tutto questo argomento passando per db, potresti usare un'implementazione singleton e chiamare db.getInstance () dove necessario.
wulfgarpro

Risposte:


237

Sulla base dei tuoi commenti in questa risposta , faccio quello che stai cercando di fare in questo modo:

module.exports = function (app, db) {
    var module = {};

    module.auth = function (req, res) {
        // This will be available 'outside'.
        // Authy stuff that can be used outside...
    };

    // Other stuff...
    module.pickle = function(cucumber, herbs, vinegar) {
        // This will be available 'outside'.
        // Pickling stuff...
    };

    function jarThemPickles(pickle, jar) {
        // This will be NOT available 'outside'.
        // Pickling stuff...

        return pickleJar;
    };

    return module;
};

Struttura praticamente tutti i miei moduli in questo modo. Sembra funzionare bene per me.


L' appargomento è necessario o posso ometterlo? Il mio modulo non farà un uso esplicito di questo argomento dell'app, ma non so se è richiesto da node.js per qualche cosa interna. Se è ok, la mia dichiarazione del modulo sarebbe simile a questa:module.exports = function (db) {
Ulysses Alves

Questo era specifico per un'app Express, quindi decisamente non necessario.
floatingLomas

@floatingLomas Il meccanismo di serializzazione in python si chiama salamoia: stackoverflow.com/questions/11218477/...
SadSeven

1
Quindi cosa succede se si fa riferimento al modulo più volte? Il primo require(mymodule)(myargs)ti darebbe un modulo con cui lavorare. Tuttavia, se lo fai riferimento da qualche altra parte da un altro modulo ?? nel sistema di base sembra esserci una cache coinvolta, ma in questo sistema, la cache restituirebbe il metodo del generatore nudo alle chiamate successive a require(), e se si passassero gli argomenti require()(someargs)si otterrebbe un modulo diverso indietro ... forse mi manca qualcosa
Tom H

2
@ TomH In tal caso, dovresti metterlo nella cache. Per farlo dovresti avere var module;al di fuori della funzione di esportazione, e quindi non appena entri in dovresti controllare se moduleè già definito, e in tal caso, restituiscilo (e in caso contrario, inizializzalo). Ha senso?
floating

37

Non sono sicuro se questo sarà ancora utile alle persone, ma con ES6 ho un modo per farlo che trovo pulito e utile.

class MyClass { 
  constructor ( arg1, arg2, arg3 )
  myFunction1 () {...}
  myFunction2 () {...}
  myFunction3 () {...}
}

module.exports = ( arg1, arg2, arg3 ) => { return new MyClass( arg1,arg2,arg3 ) }

E poi ottieni il tuo comportamento previsto.

var MyClass = require('/MyClass.js')( arg1, arg2, arg3 )

32

Sì. Nel tuo loginmodulo, esporta semplicemente una singola funzione che prende dbcome argomento. Per esempio:

module.exports = function(db) {
  ...
};

1
L'ho provato. In login.js module.exports = function(app,db) { ... } module.exports.auth = function(req,res) { ... authentication stuff } Chiama la funzione "anonymous" e imposta le variabili appe db, ma in questo caso la mia applicazione non troverà la authfunzione. Che cosa sto facendo di sbagliato? Se rimuovo la funzione anonima la authfunzione diventa nuovamente accessibile.
Andreas Selenwall

Come tutto in javascript, exportsè un oggetto. È possibile assegnargli proprietà (più esportazioni) oppure assegnarlo a un valore. Sembra che tu abbia assegnato le esportazioni a una funzione, ma poi hai assegnato l'autenticazione come proprietà della funzione che hai assegnato alle esportazioni. Quindi dovresti fare ciò var auth = require("./login.js").authche potrebbe non essere quello che volevi. Se vuoi usare lo schema della domanda originale, probabilmente è meglio attenersi a un singolo valore di esportazione. Se ancora non ha senso, consiglierei di pubblicare un riassunto da esaminare.
David Weldon

1
Dopo aver letto di nuovo questo, sembra che potresti aver assegnato authcome una proprietà exportsdell'oggetto, e poi più avanti nel modulo che hai assegnato exportsa una funzione (sovrascrivendo così l'assegnazione precedente). Se inverti l'ordine dell'assegnazione dovresti essere in grado di accedere alla authfunzione come ti aspetteresti. Anche in questo caso è difficile dirlo senza effettivamente vedere il codice.
David Weldon

1
Grazie mille per il vostro aiuto. Quello che non mi rendevo conto era esattamente quello a cui miravi con require ('login'). Auth. Pensavo non ci fossero differenze in var login = require('login')e var login = require('login')(app), ma c'è una differenza enorme, non c'è magia nella funzione anonima restituita, è solo un'altra funzione / oggetto. Invece di avere un module.exports.auth, la funzione anomima ora restituisce la funzione auth (tra le altre), cioè return { auth: authFunction, login: loginFunction}. Quindi ora funziona. Grazie.
Andreas Selenwall
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.