为什么Sock.js使用双json编码?

时间:2014-08-19 12:11:47

标签: javascript json sockjs

 var sock = new SockJS(url, {'protocols_whitelist': ['xhr-polling']});
 sock.onopen = function() {
     var msg = {msg: "hello"};
     sock.send(msg); // 1. example
     sock.send(JSON.stringify(msg)); // 2.example

 };

1。例如google chrome payload

["[object Object]"]

2。例如google chrome payload

["{\"msg\":\"hello\"}"]

我发现显式转换为字符串发生在sock.js这里(第253行):

https://github.com/sockjs/sockjs-client/blob/master/lib/sockjs.js#L253

这就是我直接发送js对象时看到["[object Object]"]的原因(因为'' + datadata转换为字符串)。

 that._transport.doSend(utils.quote('' + data));

SockJS.prototype.send = function(data) {
    var that = this;
    if (that.readyState === SockJS.CONNECTING)
        throw new Error('INVALID_STATE_ERR');
    if (that.readyState === SockJS.OPEN) {
        that._transport.doSend(utils.quote('' + data)); // here
    }
    return true;
};

但是那个utils.quote确实

https://github.com/sockjs/sockjs-client/blob/master/lib/utils.js#L292

// Quote string, also taking care of unicode characters that browsers
// often break. Especially, take care of unicode surrogates:
//    http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Surrogates

    utils.quote = function(string) {
        var quoted = quoteJSON(string);

        // In most cases this should be very fast and good enough.
        extra_escapable.lastIndex = 0;
        if(!extra_escapable.test(quoted)) {
            return quoted;
        }

        if(!extra_lookup) extra_lookup = unroll_lookup(extra_escapable);

        return quoted.replace(extra_escapable, function(a) {
            return extra_lookup[a];
        });
    }; 

最后:

https://github.com/sockjs/sockjs-client/blob/master/lib/utils.js#L261

var quoteJSON = (JSON3 && JSON3.stringify) || function(string) {
    json_escapable.lastIndex = 0;
    if (json_escapable.test(string)) {
        string = string.replace(json_escapable, function(a) {
            return json_lookup[a];
        });
    }
    return '"' + string + '"';
};

正如您所看到的那样,当您想要发送JSON时,您需要通过自己显式调用JSON.stringify,并且Sock.js在您传递给sockjs_instance.send的字符串上再次发生同样的事情。

为什么需要编码两次?问题是我需要在服务器上做一些黑客来解码消息,因为单个JSON.decode不能正常工作,因为sock.js默认将all作为字符串数组发送。这是性能问题。

1 个答案:

答案 0 :(得分:1)

  

正如您所看到的那样,当您想要发送JSON时,您需要通过自己显式调用JSON.stringify,并且Sock.js在您传递给sockjs_instance.send的字符串上再次发生同样的事情。

Websockets API假设数据传递给"发送"是文字。 (或二进制,SockJS不支持)。这就是"发送"呼叫期望它是文本。

SockJS确实需要对它进行编码,我们恰好使用json。 JSON很快(因为它经常内置)。实际上,我们使用代码中找到的修改后的JSON编码来避免unicode问题。

是的,理论上对于某些传输,在传递富数据时可以避免双重编码,但这样做不值得破坏与原生WS的兼容性。