2012-04-24 20 views
56

Tôi sử dụng các tệp bộ định tuyến riêng làm mô-đun cho ứng dụng chính và ứng dụng auth. Tôi không thể có được cách tốt nhất để truyền các biến (db client) vào các router. Tôi không muốn hardcode hoặc vượt qua nó với:Cách tốt nhất để chuyển các biến chung thành các mô-đun riêng biệt trong Node.js là gì?

module.exports = function(app, db) { 

Có lẽ cách tốt nhất để sử dụng đăng ký đơn hoặc sử dụng biến db toàn cầu?

experiense của bạn với mẫu thiết kế là gì? Cách nào là tốt nhất và tại sao?

+1

có thể trùng lặp http://stackoverflow.com/questions/8931239/how-to-access-variables-declared-in-main-app-js-in-seperate-route-files-in-node/8931366 # 8931366 –

Trả lời

99

Tôi đã tìm thấy bằng cách sử dụng tính năng tiêm phụ thuộc, để chuyển mọi thứ vào, để trở thành phong cách tốt nhất. Nó thực sự sẽ giống như bạn có:

// App.js 
module.exports = function App() { 
}; 

// Database.js 
module.exports = function Database(configuration) { 
}; 

// Routes.js 
module.exports = function Routes(app, database) { 
}; 

// server.js: composition root 
var App = require("./App"); 
var Database = require("./Database"); 
var Routes = require("./Routes"); 
var dbConfig = require("./dbconfig.json"); 

var app = new App(); 
var database = new Database(dbConfig); 
var routes = new Routes(app, database); 

// Use routes. 

này có một số lợi ích:

  • nó buộc bạn phải tách hệ thống của bạn thành các thành phần với sự phụ thuộc rõ ràng, thay vì che giấu sự phụ thuộc đâu đó trong giữa tệp nơi họ gọi require("databaseSingleton") hoặc tệ hơn, global.database.
  • Nó làm cho việc kiểm tra đơn vị rất dễ dàng: nếu tôi muốn thử nghiệm Routes cách ly, tôi có thể tiêm nó với các thông số appdatabase giả và chỉ kiểm tra mã số Routes.
  • Nó đặt tất cả các đồ thị đối tượng của bạn nối với nhau ở một nơi duy nhất, cụ thể là gốc thành phần (trong trường hợp này là server.js, điểm vào ứng dụng). Điều này mang lại cho bạn một nơi duy nhất để xem mọi thứ phù hợp với nhau như thế nào trong hệ thống.

Một trong những lời giải thích tốt hơn cho điều này mà tôi đã nhìn thấy là an interview with Mark Seeman, tác giả của cuốn sách tuyệt vời Dependency Injection trong .NET. Nó áp dụng nhiều cho JavaScript, và đặc biệt là với Node.js: require thường được sử dụng như một định vị dịch vụ cổ điển, thay vì chỉ là một hệ thống mô-đun.

+0

Tôi đang cố gắng sử dụng ví dụ này, tuy nhiên, làm thế nào để xác định các tuyến đường của tôi trong việc triển khai Routes.js vì nó nằm trong hàm Routes này? Cảm ơn! – cpeele00

+0

@ cpeele00 giống như cách bạn làm với bất kỳ phương pháp nào của lớp khác. – Domenic

+0

Khi sử dụng thiết lập này, bạn có tách riêng lộ trình của mình theo cách tương tự không? ví dụ. Các tuyến đường (ứng dụng, cơ sở dữ liệu) {routes = {social: new SocialRoutes (ứng dụng, cơ sở dữ liệu), api: ApiRoutes mới (ứng dụng, cơ sở dữ liệu)}; các tuyến trả lại; } – Stephen

2

Tôi đề nghị bạn tạo một tệp cài đặt với cá thể db và với những thứ khác mà bạn cần sử dụng trên toàn cầu như 'singleton'.

Ví dụ, tôi có settings.js với khách hàng redis db của tôi:

var redis = require('redis'); 
exports.redis = redis.createClient(6379, '127.0.0.1'); 

Và trong nhiều mô-đun khác tôi bao gồm nó:

var settings = require('./settings'); 
setting.redis.<...> 

Nhiều thời gian bao gồm nó tôi luôn luôn có một ví dụ kết nối db.

+0

Nếu tôi sử dụng mã tiếp theo: ' var redis = require ('redis'); var client = redis.createClient (6379, '127.0.0.1'); client.auth (redispass); exports.client = client; ' mô-đun này sẽ kết nối lại một lần nữa và một lần nữa, hay không? – Serg

+2

không, chỉ một kết nối. Tìm [tài liệu] (http://nodejs.org/api/modules.html#modules_caching), _Nhiều cuộc gọi đến yêu cầu ('foo') có thể không làm cho mã mô-đun được thực hiện nhiều lần_ – akaravashkin

+3

Điều rủi ro của nó là dựa vào " yêu cầu "đối với hành vi singleton, vì bạn sẽ chỉ nhận được cùng một cá thể trở lại nếu bạn vượt qua chính xác cùng một đường dẫn. Các mô-đun được lưu trữ dựa trên đường dẫn được chuyển, chứ không phải trên một đường dẫn đã được giải quyết. Nói cách khác, nó sẽ hoạt động như một singleton, cho đến khi bạn cố gắng sử dụng nó từ một thư mục con. –

0

Đó là hoàn toàn lỗi thời, nhưng bạn có thể sử dụng global trong một kịch bản:

global.foo = new Foo(); 

trong kịch bản khác:

foo.bar(); 

Bạn cũng có thể sử dụng liên tục đã tồn tại:

Object.foo = new Foo(); 

Và tại đây:

Object.foo.bar(); 
1

Bạn có thể tiết kiệm cho mình tất cả các mã soạn sẵn của dây lên các module của bạn nếu bạn sử dụng một khuôn khổ dependency injection

This answer danh sách một vài trong số họ. Tôi cũng đã xây dựng một simpler DI framework here.

EDIT: dưới đây là một bản sao hình thành câu trả lời trong trường hợp trang đó thay đổi


requirecách quản lý phụ thuộc vào Node.js và chắc chắn nó là trực quan và hiệu quả, nhưng nó cũng có những hạn chế của nó.

Lời khuyên của tôi là hãy xem xét một số thùng chứa Dependency Injection hiện có cho Node.js để có ý tưởng về ưu điểm/nhược điểm của chúng. Một số trong số đó là:

Chỉ cần đến tên một vài.

Bây giờ câu hỏi thực sự là, bạn có thể đạt được điều gì với vùng chứa DI Node.js, so với đơn giản require?

Ưu điểm: testability

  • tốt hơn: module chấp nhận phụ thuộc của họ như là đầu vào
  • Inversion of Control: quyết định làm thế nào để dây module của bạn mà không cần chạm vào mã chính của ứng dụng.
  • thuật toán tùy chỉnh để giải quyết các mô-đun: phụ thuộc có số nhận dạng "ảo", thường chúng không bị ràng buộc vào đường dẫn trên hệ thống tệp.
  • Khả năng mở rộng tốt hơn: được bật bởi số nhận dạng IoC và "ảo".
  • khác công cụ ưa thích nhất:
    • Async khởi
    • quản lý vòng đời Mô-đun
    • Khả năng mở rộng của các container DI tự
    • có thể dễ dàng thực hiện trừu tượng mức độ cao hơn (ví dụ AOP)

Nhược điểm:

  • Khác với trải nghiệm "Node.js": không sử dụng require chắc chắn có cảm giác như bạn đang lệch khỏi cách suy nghĩ của nút.
  • Mối quan hệ giữa sự phụ thuộc và triển khai của nó không phải lúc nào cũng rõ ràng. Một phụ thuộc có thể được giải quyết trong thời gian chạy và bị ảnh hưởng bởi các thông số khác nhau. Mã này trở nên khó khăn hơn để hiểu và gỡ lỗi
  • chậm thời gian khởi động
  • đáo hạn (tại thời điểm này): không ai trong số các giải pháp hiện nay là thực sự phổ biến tại thời điểm này, vì vậy không quá nhiều hướng dẫn, không có hệ sinh thái, không chiến thử nghiệm.
  • Một số vùng chứa DI sẽ không hoạt động tốt với các trình bao gói mô-đun như Browserify và Webpack.
Các vấn đề liên quan