2016-05-16 18 views
6

Tôi có khó khăn để tạo ra một mô-đun mà thấy nhiều chức năng cho thư viện Socket.IO tôi:Làm thế nào để tạo ra một mô-đun Socket.IO tái sử dụng

const sio = require('socket.io'); 
module.exports = function(server) { 
    const io = sio(server); 
    return { 
    register: function(namespace) { 
     let nsp = io.of(namespace); 
     nsp.on('connect', function(socket) { 
     // ... 
     } 
    } 
    } 
} 

Vấn đề bây giờ là làm cách nào để tận dụng điều này trong mô-đun khác ? Trong số app.js

Tôi tạo server bằng Express và có thể khởi tạo mô-đun với require('./mysocketio')(server) nhưng không phải trong các mô-đun khác vì máy chủ không khả dụng ở đó. Cách tốt nhất để giải quyết những phụ thuộc vòng tròn này là gì?

+0

Tôi nghĩ bạn nên giữ cho nó đơn giản và hiển thị 'io' từ tập lệnh bắt đầu của máy chủ (có thể là tệp app.js/web.js trong dự án của bạn) và sử dụng lại ví dụ đó trong mô-đun của bạn. – gevorg

Trả lời

1

Nó không thực sự là phụ thuộc vòng tròn; Nó chỉ là module của bạn a) phụ thuộc vào một module khác không có sẵn trên toàn cầu và b) module của bạn có lẽ được sử dụng ở nhiều nơi trong mã của bạn.

toàn cầu

Một giải pháp khả thi (với nhược điểm), là chỉ cần nạp mô-đun của bạn một lần, và đính kèm nó vào một toàn cầu: global.mysocketio = require('./mysocketio')(server);

Điều này cho phép bạn truy cập vào bất cứ nơi nào trong global.mysocketio dự án của bạn, khi dự án đã được tải. Đây là một công trình mà cá nhân tôi sử dụng cho việc xây dựng bộ ghi nhật ký riêng; Logger của tôi được sử dụng ở nhiều nơi xung quanh mã của tôi, vì vậy tôi chỉ cần giữ nó vào global.log.

Tuy nhiên, việc sử dụng hình cầu là hơi bẩn; Nó đưa ra các vấn đề với việc tách biệt không gian tên (ở đâu đó một số mã nào đó quyết định sử dụng global.mysocketio), và nó tạo ra một sự phụ thuộc 'vô hình'; Mã khác chỉ giả định rằng một toàn cầu nhất định sẽ tồn tại, và nó không phải là dễ dàng để tìm thấy những phụ thuộc.

Xuất

Một giải pháp đẹp hơn là chỉ cần vượt qua biến bất cứ nơi nào cần thiết. Có rất nhiều cách để làm điều này. Tôi hiểu rằng app.js của bạn không có sẵn biến máy chủ, nhưng chắc chắn nó bao gồm cả mã thể hiện của bạn theo một cách nào đó. Nếu bạn cần 'máy chủ' hoặc 'mysocketio' có sẵn từ app.js, chỉ cần xuất nó từ mô-đun của bạn nơi bạn đang tạo 'máy chủ'. Giống như:

module.exports.expressServerVar = server;

Chỉ cần 2 xu của tôi; Bạn có mạnh mẽ không đồng ý với tôi hay tôi thiếu một cái gì đó quan trọng? Cho tôi biết!

1

Tôi muốn sử dụng công cụ tiêm phụ thuộc hoặc nhà máy. Bạn có thể sử dụng một cái gì đó như jimple.

Nhưng đây là ví dụ không sử dụng bất kỳ phụ thuộc bên ngoài nào. Điều này là do không có nghĩa là ví dụ mã tốt nhất nhưng nó hy vọng sẽ có được điểm trên. Tôi vẫn khuyên bạn nên sử dụng jimple thay vì điều này.

// app.js 

var express = require('express'); 
var app = express(); 

var factory = require('./factory.js'); 
factory.setExpress(app); // This could also be done in the factory constructor. Or you could instanciate your express app in the factory.js class. 


// factory.js 
var socketIoModule = require('./your-socket-io-module.js') 

function Factory() { 

} 

Factory.prototype.setExpress = function(app) { 
    this.app = app; 
} 

Factory.prototype.getSocketIOModule = function() { 
    return socketIoModule(this.app); 
} 

// By exporting it this way we are making it a singleton 
// This means that each module that requires this file will 
// get the same instance of factory. 
module.exports = new Factory(); 


// some code that needs socket io module 
var factory = require('./factory.js'); 

function() { 
    var socketIo = factory.getSocketIOModule(); 

    socketIo.doStuff(); 
} 
1

cách tiếp cận mà tôi sử dụng trong các ứng dụng của tôi được phơi bày serverio trường từ kịch bản bắt đầu và tái sử dụng chúng trong các module

// Setup servers. 
var http = require('http').Server(app); 
var io = require('socket.io')(http); 

// Setup application. 
require('./server/app')(app, express, io); 

// Start listening on port. 
http.listen(configs.PORT, function() { 
    console.log("Listening on " + configs.PORT); 
}); 

Bên trong module của bạn, bạn có thể sử dụng io dụ để xử lý sự kiện thiết lập hoặc phát ra các sự kiện , một cái gì đó như thế này

module.exports = { 
    contest: function(io, contest) { 
    var namespace = io.of('/' + contest.id); 
    namespace.on('connection', function(socket) { 
     socket.on('word', function(data) { 
      ... 
     }); 
    }); 
    } 
}; 

Cho mẫu của bạn

tôi sẽ đưa phần này trong app.js hoặc trong file js được sử dụng để khởi động máy chủ

const sio = require('socket.io'); 
const io = sio(server); 

và sẽ có Socket.IO mô-đun như

module.exports = function(server, io) { 
    return { 
    register: function(namespace) { 
     let nsp = io.of(namespace); 
     nsp.on('connect', function(socket) { 
     // ... 
     } 
    } 
    } 
} 

mẫu của tôi này

2

Vâng, bạn có thể đạt được những theo những cách khác nhau, như:

  • đối tượng thiết lập để không gian tên toàn cầu. (thay đổi chăm sóc nhu cầu toàn cầu)
  • Sử dụng module.exports và yêu cầu đối tượng trong các tệp khác. (có thể dẫn đến các vấn đề phụ thuộc vòng tròn nếu không được thực hiện đúng cách)
  • chuyển trường hợp làm đối số cho bộ điều khiển, trong khi yêu cầu chúng trong các tuyến.

myModule.jsMô-đun đó cho thấy chức năng của thư viện của bạn Socket.IO

const sio = require('socket.io'); 
module.exports = function(server) { 
    const io = sio(server); 
    return { 
    register: function(namespace) { 
     let nsp = io.of(namespace); 
     nsp.on('connect', function(socket) { 
     // ... 
     } 
    } 
    } 
} 

dòng 1: thiết lập các mô-đun trong không gian tên toàn cầu.

app.js

var app = require('express').createServer(); 
var io = require('./myModule')(app); 
global._io = io; 

app.listen(80) 

controller.js

module.exports = function(io){ 
    var that={}; 
    /* 
    * Private local variable 
    * made const so that 
    * one does not alter it by mistake 
    * later on. 
    */ 
    const _io = global._io; 

    that.myAction = function(req,res){ 

     _io.register('newRoom'); 
     res.send('Done'); 
    } 
    return that; 
} 

Dòng 2: qua mô-đun như các đối số.

app.js

var app = require('express').createServer(); 
var io = require('./myModule')(app); 

require(./router.js)(app,io); 

app.listen(80); 

router.js

/* 
* Contains the routing logic 
*/ 
module.exports = function (app,io) { 
//passing while creating the instance of controller for the first time. 
var controller = require("./controller")(io); 

app.get('/test/about',controller.myAction); 
}; 

controller.js

module.exports = function(io){ 
    var that={}; 

    const _io = io; 

    that.myAction = function(req,res){ 

     _io.register('newsRoom'); 
     res.send('Done'); 
    } 

    // everything attached to that will be exposed 
    // more like making public member functions and properties. 
    return that; 
} 

Dòng 3: Thiết io đến toàn cầu. Vì vậy, không cần phải vượt qua máy chủ mỗi lần.

app.js

var app = require('express').createServer(); 
require('./myModule')(app); 

require(./router.js)(app); 

app.listen(80); 

controller.js

// no need to pass the server as io is already initialized 
const _io = require('./myModule')(); 

module.exports = function(io){ 
    var that={}; 

    that.myAction = function(req,res){ 

     _io.register('newsRoom'); 
     res.send('Done'); 
    } 
    return that; 
} 

myModule.js

module.exports = function(server) { 

    const _io = global._io || require('socket.io')(server); 

    if(global._io === undefined){ 
    //initializing io for future use 
    global._io = _io; 
    } 

    return { 
    register: function(namespace) { 
     let nsp = _io.of(namespace); 
     nsp.on('connect', function(socket) { 
     // ... 
     } 
    } 
    } 
} 

Có lẽ, cách sạch nhất là truyền là đối số cho các bộ điều khiển, trong khi yêu cầu chúng trong các tuyến. Mặc dù dòng chảy thứ 3 có vẻ đầy hứa hẹn nhưng người ta phải cẩn thận trong khi thay đổi không gian tên chung.

Các vấn đề liên quan