2014-12-31 19 views
3

我目前想知道在這種情況下什麼可能是最好的編程習慣:和的NodeJS Socket.IO:發出請求事件並得到響應,當/我應該在哪裏綁定監聽器?

假設我有客戶端連接到我的服務器。並且此客戶端請求服務器使用auth事件和他的用戶名進行身份驗證。

socket = io(); 
socket.emit('auth', "John"); 

在這個簡單的情況下,服務器與一個auth_succeed事件與用戶的ID響應。

io.on('connection', function(socket) { 
    socket.on('auth', function(username) { 
     socket.emit('auth_succeed', id); 
    } 
} 

所以我的問題是,當我還是應該在哪裏綁定在客戶端auth_succeed事件監聽器? 對我來說有兩種方法:

在發射之前,我確信,響應事件總是會得到正確處理,但會導致一些意大利麪代碼。例如:

socket = io(); 
socket.on('auth_succeed', function(id){ 
    //Do some post-auth stuff here 
}); 
socket.emit('auth', "John"); 

或者發射之後,這會導致更乾淨的代碼,但也有可能,我再猜,誤了大事,如果sended足夠快。例如:

socket = io(); 
socket.emit('auth', "John"); 
socket.on('auth_succeed', function(id){ 
    //Do some post-auth stuff here 
}); 

您對這個問題有什麼想法?

回答

4

由於從發射響應應該是異步的,並在客戶端側JS在本質上是同步的,socket.on('auth_succeed'結合從auth事件回調之前會發生。


下面的流程將發生在客戶端上...

// EXECUTION SCOPE BEGINS 
... 
// this will send a message to the server 
// the message and/or response will be sent asynchronously 
socket.emit('auth', 'John'); 
// so your code will continue before you get anything from the server 

//which means the following binding will happen before any response to the above emit 
socket.on('auth_succeed', function(id){ 
    //... handle message from server ... 
}); 
... 
// EXECUTION SCOPE ENDS 

有時封閉範圍/函數執行完畢的「auth_succeed」事件後提出。


您也可以考慮打破了你的事件處理程序...

socket.on('auth_succeed', onAuthSucceed.bind(null, socket)); 
socket.emit('auth', 'john'); 

// ... elsewhere ... 

function onAuthSucceed(socket, id) { 
    // handle message from server 
} 

這將減少你的綁定的噪音,你的信號事件,無論你選擇綁定或首先發射。

通過讓函數需要它需要的任何東西,並對事件使用綁定,所討論的方法可以位於單獨的文件/模塊中,並且更容易單獨進行測試。

+0

所以 - 複述禪宗公約 - 「首先是意大利麪,然後是沒有意大利麪,然後是......」 - 但這沒關係?你能編輯你的迴應來證明OP的異步/同步的後果嗎? –

+0

@ Tracker1就像在他的問題'io.on('connection',function(){...})'中的op狀態在服務器端一樣。因此客戶端的'socket.on('auth_succeed',...)'和服務器端的'socket.on('auth)'回調的綁定無關。 – agconti

+0

這個答案似乎完全符合我所尋找的。 socket.io文檔缺乏這種細節。 [This](http://socket.io/docs/#sending-and-getting-data-(acknowledgements))可能也適合我的問題 –

0
socket.set('authorization',function(request,callback){ 
// check authorization for username 
// set global variable flag for valid/invalid username. 
if(valid_uname){ 
return(null,true) 
} 
else{ 
return(null,false); 
} 
)}; 
//Now on socket.on check global variable flag. 
//emit when needed. 
+1

您能解釋一下您的解決方案嗎? 'socket.set()'似乎在版本1.0之後就被棄用了,我並不瞭解這個中間件是如何工作的。無論如何,謝謝你對我的問題感興趣 –

1

socket.io docs從0.9遷移,做了一個很好的工作,展示如何在1.0中驗證套接字。

一個例子,你會:

你應該創建一個認證中間件來處理這個問題。

創建一個控制器進行調用authorization.js:

/** 
* Socket.io middleware that that authorizes clients 
* @param {object} socket 
* @param {function} next 
*/ 
module.exports = function(socket, next) { 

    // do some custom auth here 
    var handshakeData = socket.request; 

    // make sure the handshake data looks good with some 
    // custom logic 
    // if doesn't you can do this: 
    // next(new Error('not authorized'); 
    // else just call next 

    next(); 
} 

在index.js只需連接中間件io.use

var authorizeSockets = require('./controllers/authorization'); 
io.use(authorizeSockets); 

使用io.set因爲socket.io 1.0現在已經貶值了io.use()

然後,您可以通過在連接事件中發出auth_suceed,讓客戶知道他們已成功授權和連接,因爲使用新的中間件就會導致套接字無法連接,除非他們成功授權。

io.on('connection', function(socket){ 
    socket.emit('auth_succeed', yourPayloadHere); 
}); 
+1

謝謝你的回答!但是認證案例純粹是理論性的,我的問題的真正需求是關於如何在將偵聽器綁定到事件時獲得良好的編程實踐。此外,這種情況主要集中在客戶端而不是服務器端。你提供了一個解決方案來處理認證服務器端,我沒有問過。 如果你認爲你可以幫助我,那麼請隨時編輯或重新發布答案 –

相關問題