2015-06-15 3 views
0

Я играю с Node, Socket.IO и BDD, создавая приложение чата. Во время одного из тестов, я получаю сообщение об ошибке тайм-аут с указанием:Сервер Socket.IO не получает сообщение от клиента

Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

Пострадавшая тест

it('#must be able to receive a message', function(done) 
{ 
    chatterServer.on('chatterMessage', function(data) 
    { 
     console.log('Incoming message!'); 
     expect(data).to.have.property('message'); 
     expect(data.message).to.be('Hello, world!'); 
     done(); 
    }); 

    console.log('Sending message!'); 
    chatterClient.send('chatterMessage', { message: 'Hello, world!' }); 
    console.log('Sent!'); 
}); 

Я обнаружил, что причиной этой проблемы является то, что chatterMessage событие не быть пойманным сервер. Пока я это определял.

выход консоли является:

Sending message!
Sent!
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

Я, вероятно, делать что-то неправильно. Я не очень хорошо знаком с Node и Socket.IO, поэтому мне очень жаль, если этот вопрос очень очевиден.

Я искал Google с поисковыми запросами «socket.io сервер не получил от клиента», но из того, что я нашел, ничто не помогло мне решить мою проблему до сих пор.

Однако я попытался решить проблему в this question, но это не исправило это для меня.

Я использую мокко и expect.js

Полный тест является:

var util = require('util'); 
var Chatter = require('../src/index'); 
var ChatterServer = Chatter.Server; 
var ChatterClient = Chatter.Client; 
var express = require('express'); 
var expect = require('expect.js'); 
var socketIO = require('socket.io'); 
var socketIOClient = require('socket.io-client'); 

var host = 'http://localhost'; 
var port = 8080; 

describe('Chatter', function() 
{ 
    'use strict'; 

    var chatterServer; 
    var chatterClient; 
    var server; 

    before(function() 
    { 
     var app = express(); 

     server = app.listen(port); 
    }); 

    beforeEach(function() 
    { 
     chatterServer = new ChatterServer(socketIO(server)); 
     chatterClient = new ChatterClient(socketIOClient, util.format('%s:%s', host, port.toString())); 
    }); 

    ... 

    it('#must be able to receive a message', function(done) 
    { 
     chatterServer.on('chatterMessage', function(data) 
     { 
      console.log('Incoming message!'); 
      expect(data).to.have.property('message'); 
      expect(data.message).to.be('Hello, world!'); 
      done(); 
     }); 

     console.log('Sending message!'); 
     chatterClient.send('chatterMessage', { message: 'Hello, world!' }); 
     console.log('Sent!'); 
    }); 
}); 

Мой клиент (ChatterClient) является:

(function() 
{ 
    'use strict'; 

    function Client(socketIO, url) 
    { 
     this.socketIO = socketIO(url); 
    } 

    Client.prototype.send = function(event, data) 
    { 
     this.socketIO.emit(event, data); 
    }; 

    Client.prototype.on = function(event, callback) 
    { 
     this.socketIO.on(event, callback); 
    }; 

    if (module !== undefined && module.hasOwnProperty('exports')) { 
     module.exports = Client; 
    } else { 
     window.Chatter = { 
      Client: Client, 
     }; 
    } 
}()); 

Сервер (ChatterServer) является:

(function() 
{ 
    'use strict'; 

    function Server(socketIO) 
    { 
     this.socketIO = socketIO; 
     this.connectedUsers = {}; 

     this.on('connection', (function(user) 
     { 
      var userID = user.client.id; 

      this.connectedUsers[userID] = user; 

      user.emit('chatterConnectionAcknowledged', { id: userID }); 
     }).bind(this)); 
    } 

    Server.prototype.on = function(event, handler) 
    { 
     this.socketIO.on(event, handler); 
    }; 

    module.exports = Server; 

}()); 

ответ

1

Вам нужно изменить код с двух сторон.

С первой стороны вам необходимо будет прослушивать входящие сокетные соединения на объекте socketIO. (См подчеркнутого кода ниже)

 
    //.. some code 

    function Server(socketIO) 
    { 
     this.socketIO = socketIO; 
     this.connectedUsers = {}; 

     this.socketIO.on('connection', (function(user) 
     { 
      var userID = user.client.id; 

      this.connectedUsers[userID] = user; 

      user.emit('chatterConnectionAcknowledged', { id: userID }); 
     }).bind(this)); 
    } 

    //.. some code 

Второй сторона, когда вы добавляете новые события для прослушивания на сервере, вы должны связать эти события с розетками, так как они являются те, которые собираются слушать, когда события выходят из сокетов.

Server.prototype.on = function (event, handler) { 
    Object.keys(this.connectedUsers).map(function (key) { 
    this.connectedUsers[key].on(event, handler); 
    }.bind(this)); 
}; 
+0

Я просто попробовал это, но проблема остается. С первой стороны я могу понять это изменение. Раньше я это делал, но менял его на 'this.on', так как он мог бы работать одинаково, но вместо этого использовал метод Server. Я знаю, что создаю некоторые накладные расходы, но я не думаю, что это большая проблема. Второе изменение, даже перед тем, как пытаться, я не согласен с тем, поскольку это зацепило бы это событие на клиенте, а не за сервер (что является предполагаемым эффектом). Кроме того, * сервер * не принимает событие для начала. Мне интересно, почему это так. – MisterBla

+0

@ TheSerenin Пожалуйста, просмотрите этот [gist] (https://gist.github.com/wilsonbalderrama/9f87787a201a55d99cc6), я попытался скопировать ваш код на эти файлы, надеюсь, что он такой же, как ваш, этот пример работает. Что касается изменения на ** второй стороне **, я предлагаю вам прописать свой пример с помощью raw socketio без создания абстракции (ChatterServer, ChatterClient), чтобы вы могли понять, почему я так делаю. – Wilson

+0

В основном я использую абстракцию, чтобы поддерживать инъекцию зависимости. Это (в данный момент) в основном используется для Клиента, так как во время тестирования клиент использует пакет socket.io-client, тогда как когда он будет в Интернете, он будет использовать глобальный объект socket.io. Я рассмотрел ваш смысл, и для меня это действительно не похоже на то, что я делаю. Я размещаю код на GitHub, найдите репо здесь: https://github.com/TheSerenin/chatter – MisterBla