Search code examples
node.jssocket.iobluebird

Using bluebird with socket.io not working


I am using simple socket.io chat example http://socket.io/get-started/chat/

And then trying to apply bluebird like this:

Promise.promisifyAll(io);

io.onAsync('connection')
.then(function(socket){
  console.log('a user connected');
  return socket.onAsync('chat message');
})
.then(function(msg){
  return io.emitAsync('chat message',msg)
})
.catch(function(error){
  console.log("something happened here")
  console.log(error);
});

For some reason this does not get to any .then and moves straight to .catch upon connection and throwing this:

Socket {
nsp:
   Namespace {
     name: '/',
     server:
      Server {
        nsps: [Object],
        _path: '/socket.io',
        _serveClient: true,
        _adapter: [Function: Adapter],
        _origins: '*:*',
        sockets: [Circular],
        eio: [Object],
        httpServer: [Object],
        engine: [Object],
        checkRequestAsync: [Function],
        serveClientAsync: [Function],
        setAsync: [Function],
        pathAsync: [Function],
        adapterAsync: [Function],
        originsAsync: [Function],
        attachAsync: [Function],
        listenAsync: [Function],
        attachServeAsync: [Function],
        serveAsync: [Function],
        bindAsync: [Function],
        onconnectionAsync: [Function],
        ofAsync: [Function],
        closeAsync: [Function],
        onAsync: [Function],
        toAsync: [Function],
        inAsync: [Function],
        useAsync: [Function],
        emitAsync: [Function],
        sendAsync: [Function],
        writeAsync: [Function],
        clientsAsync: [Function],
        compressAsync: [Function] },
     sockets: { '/#gePE_87A58Q80T9rAAAA': [Circular] },
     connected: { '/#gePE_87A58Q80T9rAAAA': [Circular] },
     fns: [],
     ids: 0,
     adapter:
      Adapter {
        nsp: [Circular],
        rooms: [Object],
        sids: [Object],
        encoder: Encoder {} },
     _events: { connection: [Function] },
     _eventsCount: 1 },
  server:
   Server {
     nsps: { '/': [Object] },
     _path: '/socket.io',
     _serveClient: true,
     _adapter: [Function: Adapter],
     _origins: '*:*',
     sockets:
      Namespace {
        name: '/',
        server: [Circular],
        sockets: [Object],
        connected: [Object],
        fns: [],
        ids: 0,
        adapter: [Object],
        _events: [Object],
        _eventsCount: 1 },
     eio:
      Server {
        clients: [Object],
        clientsCount: 1,
        pingTimeout: 60000,
        pingInterval: 25000,
        upgradeTimeout: 10000,
        maxHttpBufferSize: 100000000,
        transports: [Object],
        allowUpgrades: true,
        allowRequest: [Function: bound ],
        cookie: 'io',
        cookiePath: false,
        perMessageDeflate: [Object],
        httpCompression: [Object],
        ws: [Object],
        _events: [Object],
        _eventsCount: 1 },
     httpServer:
      Server {
        domain: null,
        _events: [Object],
        _eventsCount: 5,
        _maxListeners: undefined,
        _connections: 3,
        _handle: [Object],
        _usingSlaves: false,
        _slaves: [],
        _unref: false,
        allowHalfOpen: true,
        pauseOnConnect: false,
        httpAllowHalfOpen: false,
        timeout: 120000,
        _pendingResponseData: 0,
        _connectionKey: '6::::3000' },
     engine:
      Server {
        clients: [Object],
        clientsCount: 1,
        pingTimeout: 60000,
        pingInterval: 25000,
        upgradeTimeout: 10000,
        maxHttpBufferSize: 100000000,
        transports: [Object],
        allowUpgrades: true,
        allowRequest: [Function: bound ],
        cookie: 'io',
        cookiePath: false,
        perMessageDeflate: [Object],
        httpCompression: [Object],
        ws: [Object],
        _events: [Object],
        _eventsCount: 1 },
     checkRequestAsync: [Function],
     serveClientAsync: [Function],
     setAsync: [Function],
     pathAsync: [Function],
     adapterAsync: [Function],
     originsAsync: [Function],
     attachAsync: [Function],
     listenAsync: [Function],
     attachServeAsync: [Function],
     serveAsync: [Function],
     bindAsync: [Function],
     onconnectionAsync: [Function],
     ofAsync: [Function],
     closeAsync: [Function],
     onAsync: [Function],
     toAsync: [Function],
     inAsync: [Function],
     useAsync: [Function],
     emitAsync: [Function],
     sendAsync: [Function],
     writeAsync: [Function],
     clientsAsync: [Function],
     compressAsync: [Function] },
  adapter:
   Adapter {
     nsp:
      Namespace {
        name: '/',
        server: [Object],
        sockets: [Object],
        connected: [Object],
        fns: [],
        ids: 0,
        adapter: [Circular],
        _events: [Object],
        _eventsCount: 1 },
     rooms: { '/#gePE_87A58Q80T9rAAAA': [Object] },
     sids: { '/#gePE_87A58Q80T9rAAAA': [Object] },
     encoder: Encoder {} },
  id: '/#gePE_87A58Q80T9rAAAA',
  client:
   Client {
     server:
      Server {
        nsps: [Object],
        _path: '/socket.io',
        _serveClient: true,
        _adapter: [Function: Adapter],
        _origins: '*:*',
        sockets: [Object],
        eio: [Object],
        httpServer: [Object],
        engine: [Object],
        checkRequestAsync: [Function],
        serveClientAsync: [Function],
        setAsync: [Function],
        pathAsync: [Function],
        adapterAsync: [Function],
        originsAsync: [Function],
        attachAsync: [Function],
        listenAsync: [Function],
        attachServeAsync: [Function],
        serveAsync: [Function],
        bindAsync: [Function],
        onconnectionAsync: [Function],
        ofAsync: [Function],
        closeAsync: [Function],
        onAsync: [Function],
        toAsync: [Function],
        inAsync: [Function],
        useAsync: [Function],
        emitAsync: [Function],
        sendAsync: [Function],
        writeAsync: [Function],
        clientsAsync: [Function],
        compressAsync: [Function] },
     conn:
      Socket {
        id: 'gePE_87A58Q80T9rAAAA',
        server: [Object],
        upgrading: false,
        upgraded: false,
        readyState: 'open',
        writeBuffer: [Object],
        packetsFn: [Object],
        sentCallbackFn: [],
        cleanupFn: [Object],
        request: [Object],
        remoteAddress: '::1',
        checkIntervalTimer: null,
        upgradeTimeoutTimer: null,
        pingTimeoutTimer: [Object],
        transport: [Object],
        _events: [Object],
        _eventsCount: 3 },
     encoder: Encoder {},
     decoder: Decoder { reconstructor: null, _callbacks: [Object] },
     id: 'gePE_87A58Q80T9rAAAA',
     request:
      IncomingMessage {
        _readableState: [Object],
        readable: false,
        domain: null,
        _events: {},
        _eventsCount: 0,
        _maxListeners: undefined,
        socket: [Object],
        connection: [Object],
        httpVersionMajor: 1,
        httpVersionMinor: 1,
        httpVersion: '1.1',
        complete: true,
        headers: [Object],
        rawHeaders: [Object],
        trailers: {},
        rawTrailers: [],
        upgrade: false,
        url: '/socket.io/?EIO=3&transport=polling&t=LSa9q5d',
        method: 'GET',
        statusCode: null,
        statusMessage: null,
        client: [Object],
        _consuming: true,
        _dumped: true,
        _query: [Object],
        res: [Object],
        cleanup: [Function: cleanup],
        read: [Function] },
     onclose: [Function: bound ],
     ondata: [Function: bound ],
     onerror: [Function: bound ],
     ondecoded: [Function: bound ],
     sockets: { '/#gePE_87A58Q80T9rAAAA': [Circular] },
     nsps: { '/': [Circular] },
     connectBuffer: [] },
  conn:
   Socket {
     id: 'gePE_87A58Q80T9rAAAA',
     server:
      Server {
        clients: [Object],
        clientsCount: 1,
        pingTimeout: 60000,
        pingInterval: 25000,
        upgradeTimeout: 10000,
        maxHttpBufferSize: 100000000,
        transports: [Object],
        allowUpgrades: true,
        allowRequest: [Function: bound ],
        cookie: 'io',
        cookiePath: false,
        perMessageDeflate: [Object],
        httpCompression: [Object],
        ws: [Object],
        _events: [Object],
        _eventsCount: 1 },
     upgrading: false,
     upgraded: false,
     readyState: 'open',
     writeBuffer: [ [Object] ],
     packetsFn: [ undefined ],
     sentCallbackFn: [],
     cleanupFn: [ [Function], [Function] ],
     request:
      IncomingMessage {
        _readableState: [Object],
        readable: false,
        domain: null,
        _events: {},
        _eventsCount: 0,
        _maxListeners: undefined,
        socket: [Object],
        connection: [Object],
        httpVersionMajor: 1,
        httpVersionMinor: 1,
        httpVersion: '1.1',
        complete: true,
        headers: [Object],
        rawHeaders: [Object],
        trailers: {},
        rawTrailers: [],
        upgrade: false,
        url: '/socket.io/?EIO=3&transport=polling&t=LSa9q5d',
        method: 'GET',
        statusCode: null,
        statusMessage: null,
        client: [Object],
        _consuming: true,
        _dumped: true,
        _query: [Object],
        res: [Object],
        cleanup: [Function: cleanup],
        read: [Function] },
     remoteAddress: '::1',
     checkIntervalTimer: null,
     upgradeTimeoutTimer: null,
     pingTimeoutTimer:
      { _called: false,
        _idleTimeout: 85000,
        _idlePrev: [Object],
        _idleNext: [Object],
        _idleStart: 6060,
        _onTimeout: [Function],
        _repeat: null },
     transport:
      XHR {
        readyState: 'open',
        discarded: false,
        closeTimeout: 30000,
        maxHttpBufferSize: 100000000,
        httpCompression: [Object],
        supportsBinary: true,
        _events: [Object],
        _eventsCount: 5,
        sid: 'gePE_87A58Q80T9rAAAA',
        req: null,
        res: null,
        writable: false },
     _events:
      { close: [Object],
        data: [Function: bound ],
        error: [Function: bound ] },
     _eventsCount: 3 },
  rooms: { '/#gePE_87A58Q80T9rAAAA': '/#gePE_87A58Q80T9rAAAA' },
  acks: {},
  connected: true,
  disconnected: false,
  handshake:
   { headers:
      { host: 'localhost:3000',
        connection: 'keep-alive',
        'user-agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (K
HTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
        accept: '*/*',
        referer: 'http://localhost:3000/',
        'accept-encoding': 'gzip, deflate, sdch',
        'accept-language': 'ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4',
        cookie: 'io=Evc9ZXFabxXte1XXAAAB' },
     time: 'Tue Sep 13 2016 17:25:34 GMT+0200 (W. Europe Summer Time)',
     address: '::1',
     xdomain: false,
     secure: false,
     issued: 1473780334962,
     url: '/socket.io/?EIO=3&transport=polling&t=LSa9q5d',
     query: { EIO: '3', transport: 'polling', t: 'LSa9q5d' } } }

Any idea why this is not working?


Solution

  • You cannot use Bluebird's .promisifyAll() for common event handlers such as .on() for a variety of reasons.

    1. The event handler can be called more than once. Promises only resolve once.
    2. .promisifyAll() requires an async operation where the last argument is a node.js calling style function with a signature such as fn(err, data). The .on() method does not follow that convention.

    The likely reason it goes right to the .catch() handler is that your first argument is non-null which makes Bluebird thinks it has an error (per the above calling convention that it expects).


    Promises are not an appropriate match for event handlers that can be called more than once. Because the promise will only ever resolve once, you can only ever get one notification for an event using a promise. For regular event handlers, promises are not recommended - use callbacks.