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,否则:)