Socket.IO 和 IE8 - jsonp-polling 连接总是失败
Posted
技术标签:
【中文标题】Socket.IO 和 IE8 - jsonp-polling 连接总是失败【英文标题】:Socket.IO and IE8 - jsonp-polling connections always failing 【发布时间】:2013-09-09 09:12:48 【问题描述】:值得注意的是:以下是通过 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 为空或不是对象”)不同。我知道这个对象是空的,我不明白为什么它是空的。
........
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!! ***
);
.........
【问题讨论】:
看来我的问题一开始就被截断了。对这个问题有很好的描述。本质上,我提供的代码使用 jsonp-polling 进行了简单的 socket.io 连接。 IE8 它不适用于我上面已经描述的所有细节。感谢收看。 你也试过IE 9吗?如果是,请也回复 html 代码,包括标题、文档类型、所有部分,直到带有正文打开标签。然后您可以更改实际内容。如果你能创造一个很棒的小提琴。 IE8是否支持.addEventListener()
我知道Opera不支持或不习惯,你必须使用实际事件。即.onload()
您能否在您从库中粘贴的代码的位置发布指向 SocketIO 的 github 源文件的链接?指向小提琴的链接也很好,我想查看您的 index.html 文件并查看您尝试延迟加载或在其他 JS 文件中动态注入脚本标签的任何地方。
【参考方案1】:
根据this answer,我认为IE8 不支持XMLHttpRequest()
对象或XDomainRequest()
的.addEventListener()
方法(或大多数其他方法,它似乎是后来添加的)。
尝试将这部分代码重写为:
xhr.onload=function ()
set_up_socket(this, sessionString);
;
如果您想为其他现代浏览器保持相同的语法,您可以通过将其包装在条件中来回填:
if(typeof xhr.addEventListener === undefined)
xhr.onload=function ()
set_up_socket(this, sessionString);
;
不知道它是否能解决问题,但可能会有所帮助。
MDN 说"More recent browsers, including Firefox, also support listening to the XMLHttpRequest events via standard addEventListener APIs in addition to setting on* properties to a handler function."。同样,我不确定,因为他们没有说明哪些浏览器以及何时,但最好我可以告诉 IE8 不支持它。
【讨论】:
【参考方案2】:IE8 和 less 使用 attachEvent ...但它不适用于 XMLHttpRequest
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener#Compatibility
如果对 JS 的某些问题有疑问,请先停止 MDN,然后再停止 :)
【讨论】:
以上是关于Socket.IO 和 IE8 - jsonp-polling 连接总是失败的主要内容,如果未能解决你的问题,请参考以下文章
socket.io 中 io.on 和 socket.on 的区别