การส่งผ่านอาร์กิวเมนต์ที่ต้องการ (เมื่อโหลดโมดูล)


114

เป็นไปได้ไหมที่จะส่งผ่านอาร์กิวเมนต์เมื่อโหลดโมดูลโดยใช้ require

ฉันมีโมดูล login.js ซึ่งมีฟังก์ชันการเข้าสู่ระบบ ต้องมีการเชื่อมต่อฐานข้อมูลและฉันต้องการให้ใช้การเชื่อมต่อฐานข้อมูลเดียวกันในโมดูลทั้งหมดของฉัน ตอนนี้ฉันส่งออกฟังก์ชัน login.setDatabase (... ) ซึ่งให้ฉันระบุการเชื่อมต่อฐานข้อมูลและใช้งานได้ดี แต่ฉันอยากจะส่งผ่านฐานข้อมูลและข้อกำหนดอื่น ๆ เมื่อฉันโหลดโมดูล

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

ฉันค่อนข้างใหม่กับ NodeJS และมักจะพัฒนาโดยใช้ Java และ Spring Framework ใช่ ... นี่คือการฉีดตัวสร้าง :) เป็นไปได้ไหมที่จะทำบางอย่างเช่นรหัสที่ฉันให้ไว้ด้านบน?


ฉันยังอยากแนะนำให้มองไปที่คำตอบนี้คำถาม ดังที่ได้ระบุไว้ในคำตอบของฉันสำนวนทั่วไปคือการส่งผ่านappวัตถุไปยังโมดูลที่ต้องการ
David Weldon

แทนที่จะส่งอาร์กิวเมนต์ทั้งหมดนี้สำหรับ db คุณสามารถใช้การใช้งานแบบซิงเกิลตันและเรียกใช้ db.getInstance () ได้ตามต้องการ
wulfgarpro

คำตอบ:


237

จากความคิดเห็นของคุณในคำตอบนี้ฉันทำในสิ่งที่คุณพยายามทำดังนี้:

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

ฉันจัดโครงสร้างโมดูลทั้งหมดของฉันแบบนั้น ดูเหมือนจะทำงานได้ดีสำหรับฉัน


เป็นappอาร์กิวเมนต์จำเป็นหรือฉันสามารถ ommit มันได้หรือไม่ โมดูลของฉันจะไม่ใช้อาร์กิวเมนต์ของแอปนี้อย่างชัดเจน แต่ฉันไม่รู้ว่า node.js จำเป็นสำหรับบางสิ่งภายในหรือไม่ ถ้าเป็นไปได้การประกาศโมดูลของฉันจะมีลักษณะดังนี้module.exports = function (db) {
Ulysses Alves

นั่นเป็นเรื่องเฉพาะสำหรับแอป Express ดังนั้นจึงไม่จำเป็นอย่างแน่นอน
floatingLomas

@floatingLomas กลไกการทำให้เป็นอนุกรมใน python เรียกว่า pickle: stackoverflow.com/questions/11218477/…
SadSeven

1
จะเกิดอะไรขึ้นถ้าคุณอ้างอิงโมดูลหลายครั้ง? ขั้นแรกrequire(mymodule)(myargs)จะให้โมดูลที่ใช้งานได้ อย่างไรก็ตามหากคุณอ้างอิงที่อื่นจากโมดูลอื่น ?? ในระบบพื้นฐานดูเหมือนจะมีแคชที่เกี่ยวข้อง แต่ในระบบนี้แคชจะส่งคืนวิธีการกำเนิดเปลือยในการโทรครั้งต่อ ๆ ไปrequire()และถ้าคุณส่ง args ไปrequire()(someargs)คุณจะได้รับโมดูลอื่นกลับมา ... บางทีฉันอาจจะหายไป บางสิ่งบางอย่าง
Tom H

2
@TomH ในกรณีนี้คุณต้องการแคช ในการทำเช่นนั้นคุณจะมีvar module;นอกฟังก์ชันการส่งออกจากนั้นทันทีที่คุณเข้ามาในสิ่งที่คุณต้องการตรวจสอบว่าmoduleมีการกำหนดไว้แล้วหรือไม่และถ้าเป็นเช่นนั้นให้ส่งคืน (และหากไม่เป็นเช่นนั้นให้เริ่มต้น) มันสมเหตุสมผลไหม
floatingLomas

37

ฉันไม่แน่ใจว่าสิ่งนี้จะยังมีประโยชน์กับผู้คนหรือไม่ แต่ด้วย ES6 ฉันมีวิธีทำที่ฉันคิดว่าสะอาดและมีประโยชน์

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

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

จากนั้นคุณจะได้รับพฤติกรรมที่คาดหวัง

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

32

ใช่. ในloginโมดูลของคุณเพียงส่งออกฟังก์ชันเดียวที่ใช้dbเป็นอาร์กิวเมนต์ ตัวอย่างเช่น:

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

1
ฉันลองสิ่งนี้แล้ว ใน login.js module.exports = function(app,db) { ... } module.exports.auth = function(req,res) { ... authentication stuff } มันไม่เรียกว่า "ไม่ระบุชื่อ" ฟังก์ชั่นและชุดappและdbตัวแปร แต่เมื่อทำเช่นนี้ใบสมัครของฉันจะไม่พบauthฟังก์ชั่น ผมทำอะไรผิดหรือเปล่า? ถ้าฉันลบฟังก์ชันที่ไม่ระบุตัวตนauthฟังก์ชันจะสามารถเข้าถึงได้อีกครั้ง
Andreas Selenwall

เช่นเดียวกับทุกสิ่งในจาวาสคริปต์exportsคือวัตถุ คุณสามารถกำหนดคุณสมบัติให้กับมัน (การส่งออกหลายรายการ) หรือคุณจะกำหนดให้เป็นค่าก็ได้ ดูเหมือนว่าคุณกำหนดการส่งออกไปยังฟังก์ชัน แต่จากนั้นกำหนด auth เป็นคุณสมบัติของฟังก์ชันที่คุณกำหนดให้กับการส่งออก ดังนั้นคุณต้องทำvar auth = require("./login.js").authซึ่งอาจไม่ใช่สิ่งที่คุณตั้งใจไว้ หากคุณต้องการใช้รูปแบบจากคำถามเดิมคุณควรยึดตามมูลค่าการส่งออกเดียว หากยังไม่สมเหตุสมผลฉันขอแนะนำให้โพสต์ส่วนสำคัญให้ฉันดู
David Weldon

1
หลังจากอ่านสิ่งนี้อีกครั้งดูเหมือนว่าคุณอาจกำหนดให้authเป็นคุณสมบัติของexportsอ็อบเจ็กต์และต่อมาในโมดูลที่คุณกำหนดให้exportsกับฟังก์ชัน (ซึ่งจะแทนที่การกำหนดก่อนหน้านี้) หากคุณย้อนกลับลำดับของงานคุณควรจะสามารถเข้าถึงauthฟังก์ชันได้ตามที่คุณคาดหวัง อีกครั้งเป็นการยากที่จะบอกได้โดยไม่ต้องเห็นรหัสจริงๆ
David Weldon

1
ขอบคุณมาก ๆ สำหรับความช่วยเหลือของคุณ. สิ่งที่ฉันไม่ทราบคือสิ่งที่คุณตั้งเป้าไว้ด้วยความต้องการ ('เข้าสู่ระบบ') auth. แม้ว่าจะไม่มีความแตกต่างvar login = require('login')และvar login = require('login')(app)แต่มีความแตกต่างอย่างมากไม่มีเวทย์มนตร์ในฟังก์ชันนิรนามที่ส่งคืนมันเป็นเพียงฟังก์ชัน / วัตถุอื่น แทนที่จะมีmodule.exports.authฟังก์ชั่น anomymous ตอนนี้กลับฟังก์ชั่นการตรวจสอบสิทธิ์ (amongs อื่น ๆ ) return { auth: authFunction, login: loginFunction}คือ ตอนนี้ใช้งานได้แล้ว ขอบคุณ
Andreas Selenwall
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.