具有承诺或异步回调的Socket.io

时间:2014-02-10 13:11:19

标签: javascript node.js socket.io

这可能是一种反模式,但是使用promise callback从客户端向服务器发送数据时,模拟a socket.io的最佳方法是什么?

对于某些事件,我非常希望它表现得像普通的get请求,因此客户端将数据发送到服务器,服务器可以回复响应,然后解析或拒绝承诺。

3 个答案:

答案 0 :(得分:6)

这就是我的所作所为。我创建了一个发出socket命令的函数,然后返回一个promise。我的一个警告是,我还没有完成这个代码,所以可能需要一些调整。它还需要Q for its promises/deferreds

客户端功能定义:

var EmitPromise = function( socket, command, data ) {

    var deferred = Q.defer();

    socket.emit(command, data, function( response ) {

        if( typeof response === "object" ) {

            if( response.success === true ) {

                deferred.resolve(response.data);

            } else {
                if( typeof response.message === "string" ) {
                    deferred.reject( response.message );
                } else {
                    deferred.reject( "The request was not successful." )
                }
            }
        } else {

            deferred.reject( "The response to your request could not be parsed." );
        }

    });

    return deferred.promise.timeout( 30000, "The request took too long to respond." );
}

拨打电话的客户端代码:

EmitPromise( socket, "getValue", "username" )
.then(
    function( data ) {

        console.log(data);
        return EmitPromise( socket, "getValue", "anotherValue" );

    }, function( message ) {
        console.log(message);
    }
).then(
    //Chain your commands from here
);

服务器端处理程序

这个处理程序最重要的部分是必须使用包含"成功"包含真值或假值的键。这是我决定在服务器端出现某种错误时提供拒绝承诺的方法。

socket.on( 'getValue', function( valueName, setValueResult ) {

    var value = getValue(valueName) //Do something with value here

    if( value ) {
        setValueResult({
            success : success,
            data : value
        });
    } else {
        setValueResult({
            success : success
            message : "Unable to retrieve value"
        });
    }
}

答案 1 :(得分:1)

嗯,你必须跟踪请求。所以我会从一个“全局”计数器开始(它不一定是全局的,它足以让它在下面定义的两个函数中可见),它将在每个请求上增加(并与它一起发出)和一个“全局”处理程序名称代码可能如下所示:

var COUNTER = 0,
    HANDLERS = {};

var custom_get = function(data, clb) {
    COUNTER++;
    var msg = {id: COUNTER, data: data};
    socket.emit("GET", JSON.stringify(msg));
    HANDLERS[COUNTER] = clb;    
};

socket.on("GET", function(data) {
    var res = JSON.parse(data);
    HANDLERS[res.id](res.data);
    delete HANDLERS[res.id];
});

现在您只需要确保服务器将以相同的格式响应,即JSON

{id:X, data:Y}

并将对同一请求使用相同的ID。您可以像这样使用此代码:

custom_get("test", function(res) {
    console.log(res);
});

您还可以使用该代码添加例如超时。

最后看看JSON-RPC。这是一个简单的合适协议,您可以通过WebSocket轻松实现它。

答案 2 :(得分:1)

当前的socket.io版本2.1.0允许向服务器发送回调函数:

<强>客户端

socket.emit('ferret', 'tobi', (data) => {
  console.log(data); // data will be 'woot'
});

服务器

socket.on('ferret', (name, callback) => {
  callback('woot');
});

您还可以在发出之前创建一个promise,并在客户端回调函数中解析它。