Socket.IO和IE8 – jsonp-polling连接总是失败

值得注意的是:以下是通过https跨域进行的。 老实说,我认为这不是问题,因为在IE10,Chrome和FF中一切正常。 我的猜测是它可能是IE8中的XDomainRequest对象差异? 不过不确定。

下面的sendLoginRequest方法是首先调用的方法。 所有其他支持代码也在下面提供。

这一切都非常简单,但不确定为什么IE8会失败。

 function WrappedSocket(data, session_string) { var clientSocket = io.connect('https://xxxxxxxx/socketio', { query: "session=" + encodeURIComponent(session_string), transports: ['jsonp-polling'] }); clientSocket.socket.on("connect", function () { console.log("CONNECT_SUCCEED"); }); clientSocket.socket.on("connect_failed", function () { console.log("CONNECT_FAILED"); }); clientSocket.socket.on("reconnect_failed", function () { console.log("RECONNECT_FAILED"); }); clientSocket.socket.on("error", function (eobj) { console.log("Socket error " + eobj); }); console.log("Made a socket that is talking"); } var my_socket; function set_up_socket(data, sessionString) { setSession(data.responseText); my_socket = new WrappedSocket(data, sessionString); my_socket.socket.emit("message", "Howdy!"); } function sendLoginRequest(loginCode, nextRequest) { var xhr = createCORSRequest('POST', 'https://xxxxx/login', false); var sessionString = 'xxxx'; if ("withCredentials" in xhr) { xhr.addEventListener("load", function () { set_up_socket(this, sessionString); }, false); } else { xhr.onload = function () { set_up_socket(this, sessionString); }; } xhr.send(); } function createCORSRequest(method, url, onload) { xhrObj = new XMLHttpRequest(); if ("withCredentials" in xhrObj) { // Check if the XMLHttpRequest object has a "withCredentials" property. // "withCredentials" only exists on XMLHTTPRequest2 objects. if (onload) { xhrObj.addEventListener("load", onload, false); } xhrObj.open(method, url, true); xhrObj.withCredentials = true; } else if (typeof XDomainRequest != "undefined") { // Otherwise, check if XDomainRequest. // XDomainRequest only exists in IE, and is IE's way of making CORS requests. xhrObj = new XDomainRequest(); xhrObj.open(method, url); if (onload) { xhrObj.onload = onload; } } else { // Otherwise, CORS is not supported by the browser. xhrObj = null; } return xhrObj; } 

我在控制台和Fiddler轮询中看到的错误实际上正在发生,但每次轮询都会出现相同的故障:

 LOG:CONNECT_FAILED 'f.parentNode' is null or not an object 'f.parentNode' is null or not an object LOG:CONNECT_FAILED 'f.parentNode' is null or not an object 'f.parentNode' is null or not an object LOG:CONNECT_FAILED 'f.parentNode' is null or not an object 'f.parentNode' is null or not an object LOG:CONNECT_FAILED 'f.parentNode' is null or not an object 'f.parentNode' is null or not an object LOG:CONNECT_FAILED 'f.parentNode' is null or not an object 'f.parentNode' is null or not an object LOG:CONNECT_FAILED 'f.parentNode' is null or not an object 'f.parentNode' is null or not an object 

…………

(你明白了,这种情况一遍又一遍地发生。)

同样,您可以看到每个请求一个接一个地触发,来自服务器的所有200个响应但都导致来自socket.io.js文件的CONNECT_FAILED和JS错误。

最后,这是来自客户端上的socket.io.js文件的代码,该代码打破了上面在控制台屏幕截图中看到的错误(“f.parentNode为null或不是对象”)。 我理解对象是null,我没有得到的是为什么它是null。

 ........ if (this.isXDomain() && !io.util.ua.hasCORS) { var insertAt = document.getElementsByTagName('script')[0] , script = document.createElement('script'); script.src = url + '&jsonp=' + io.j.length; insertAt.parentNode.insertBefore(script, insertAt); io.j.push(function (data) { complete(data); script.parentNode.removeChild(script); // *** BREAKS HERE!! *** }); ......... 

根据这个答案 ,我不认为IE8支持XMLHttpRequest()对象的XDomainRequest()方法或XDomainRequest() (或大多数其他方法,它似乎稍后添加)。

尝试将代码的这一部分重写为:

 xhr.onload=function () { set_up_socket(this, sessionString); }; 

如果要为其他现代浏览器保留相同的语法,可以通过将其包装在条件中来回填:

 if(typeof xhr.addEventListener === undefined) { xhr.onload=function () { set_up_socket(this, sessionString); }; } 

不知道它是否会解决问题,但可能有所帮助。

MDN说“除了将*属性设置为处理函数之外,更新的浏览器,包括Firefox,还支持通过标准的addEventListener API监听XMLHttpRequest事件。” 。 再说一次,我不确定,因为他们不说哪些浏览器,何时,但最好我可以告诉IE8不支持它。

IE8和更少使用attachEvent …但它不适用于XMLHttpRequest

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener#Compatibility

如果对JS的某些问题有疑问,请先停止MDN,否则:)