Promisify Socket.IO / EventEmitter

时间:2016-05-21 16:11:56

标签: javascript node.js socket.io promise

当我在Google上搜索Promisify Socket.IO时,我感到有点惊讶。这是不常见的吗?

我也有麻烦自己宣传:

Promise.promisifyAll(io)
io.onceAsync('connect')
.then((socket) => ...)
.catch((err) => console.log(error))

这总是会触发错误情况,我假设因为.once是一个只有一个参数的回调,其中Promises期望第一个参数是错误。知道如何处理这类事情吗?

1 个答案:

答案 0 :(得分:25)

我可以想到承诺一般不适合socket.io和EventEmitter接口的几个原因:

  1. 在大多数情况下,socket.io是一个事件驱动的接口,并且承诺不会在架构上与可能出现多次的事件对齐(因为承诺是一次性设备)。是的,您可以使用.connect()的承诺,但不能使用传入消息。因此,大多数人(包括我自己)可能认为使用promises半边界而另一半使用事件处理程序是有意义的。最好在整个API中使用一个模型。

  2. Promise.promisifyAll()需要node.js样式的异步回调(错误值作为第一个参数,数据作为第二个参数),这不是任何socket.io事件处理程序回调的内容使用。为了使承诺与connect事件一起工作,您必须编写自己的自定义promsification,这可能比仅使用它所编写的事件处理程序更多的工作。

  3. 如果您尝试将事件的下一次出现与其他异步事件(通常不会做的事情)进行协调,则上述情况可能是例外情况,在这种情况下,承诺可能对协调有用。例如,假设您想知道三个单独的异步操作何时全部完成,其中一个是下一次发生的socket.io事件。然后,手动宣传该事件可能是有意义的,这样您就可以使用promises来协调多个异步操作。

    但是对于正常的socket.io用法,承诺并不是一个很好的架构设计。同样,您通常不会在网页中使用promises作为点击处理程序。

    仅供参考,如果您只想宣传connect操作,可以像这样手动执行:

    io.connectAsync = function(url, options) {
        return new Promise(function(resolve, reject) {
            io.connect(url, options);
            io.once('connect', function(socket) {
                resolve(socket);
            });
            io.once('connect_error', function() {
                reject(new Error('connect_error'));
            });
            io.once('connect_timeout', function() {
                reject(new Error('connect_timeout'));
            });
        });
    }
    
    
    io.connectAsync().then(function(socket) {
        // connected here
        socket.on('someMsg', function() {
           // process message here
        });
    }, function(err) {
        // error connecting here
    });