Internet explorer IE中缺少通过信号器的原型方法
我遇到了一个处理原型方法消失的问题(在本例中是Array.prototype方法),仅在IE中,并且仅当数组通过信号器时 我编写了一个小型/愚蠢但简单的概念验证web应用程序来演示这个问题(代码如下)。请注意,当您单击“更新所有客户机”然后单击“包含字母“r”的水果”时,“U”列表中的原型方法将丢失,从而导致异常。在这种情况下,阵列来自信号器。现在,当您单击“重置”并将数组重置为硬编码值时,“包含字母“r”的水果”按钮突然起作用-原型方法又回来了。记住,这个问题只发生在IE中 提示:当我第一次写概念证明时,我无法重现这个问题。当数组通过SignalR发送时,IE仍然使用原型方法,但当加载页面时,我确实出现了另一个错误。我意外地包含了两次jQuery。当我取出多余的脚本来包含第二个jQuery时,它修复了这个错误(很明显),但是现在这个问题可以重现了。IE当时错过了我创建的数组原型方法,但只有当数组通过信号器时 myExtensions.js:Internet explorer IE中缺少通过信号器的原型方法,internet-explorer,prototype,signalr,Internet Explorer,Prototype,Signalr,我遇到了一个处理原型方法消失的问题(在本例中是Array.prototype方法),仅在IE中,并且仅当数组通过信号器时 我编写了一个小型/愚蠢但简单的概念验证web应用程序来演示这个问题(代码如下)。请注意,当您单击“更新所有客户机”然后单击“包含字母“r”的水果”时,“U”列表中的原型方法将丢失,从而导致异常。在这种情况下,阵列来自信号器。现在,当您单击“重置”并将数组重置为硬编码值时,“包含字母“r”的水果”按钮突然起作用-原型方法又回来了。记住,这个问题只发生在IE中 提示:当我第一次写
Array.prototype.where = function (del)
{
var ret = new Array();
for (var i = 0; i < this.length; i++)
{
if (del(this[i])) ret.push(this[i]);
}
return ret;
}
Array.prototype.select = function (del)
{
var ret = new Array();
for (var i = 0; i < this.length; i++)
{
ret.push(del(this[i]));
}
return ret;
}
Index.cshtml
@{
ViewBag.Title = "Home Page";
}
@if(false)
{
@Scripts.Render("~/Scripts/jquery.signalR-1.0.0-rc1.js")
@Scripts.Render("~/Scripts/myExtensions.js")
<script src="~/signalr/hubs"></script>
}
<script type="text/javascript">
var _fruits = ["blueberry", "grape", "orange", "strawberry"].select(function (f) { return { "Name": f } });
var _list;
var conn = $.connection.listHub;
$.connection.hub.start();
conn.client.updateList = function (data)
{
_list = data;
$("#theList").html("");
for (var i = 0; i < _list.length; i++)
{
$("#theList").append("<li>" + _list[i].Name + "</li>");
}
}
$(document).ready(function ()
{
$("#cmdUpdateClients").click(function ()
{
conn.server.runTest();
});
$("#cmdReset").click(function ()
{
conn.client.updateList(_fruits);
});
$("#cmdRunTest").click(function ()
{
var message = "";
var fruitsContaining = _list
.where(function (f) { return f.Name.indexOf('r') >= 0 })
.select(function (f) { return f.Name });
for (var i = 0; i < fruitsContaining.length; i++)
{
message += " - " + fruitsContaining[i] + "\n";
}
alert(message);
});
conn.client.updateList(_fruits);
});
</script>
<input type="button" id="cmdUpdateClients" value="Update All Clients" />
<input type="button" id="cmdReset" value="Reset" />
<input type="button" id="cmdRunTest" value="Fruits containing the letter r." />
<ul id="theList"></ul>
@{
ViewBag.Title=“主页”;
}
@if(false)
{
@Scripts.Render(“~/Scripts/jquery.signalR-1.0.0-rc1.js”)
@Scripts.Render(“~/Scripts/myExtensions.js”)
}
var_fruits=[“蓝莓”、“葡萄”、“橙子”、“草莓”]。选择(函数(f){return{“Name”:f});
var_表;
var conn=$.connection.listHub;
$.connection.hub.start();
conn.client.updateList=函数(数据)
{
_列表=数据;
$(“#列表”).html(“”);
对于(变量i=0;i<\u list.length;i++)
{
$(“#列表”)。追加(“”+_列表[i]。名称+” ”;
}
}
$(文档).ready(函数()
{
$(“#cmdUpdateClient”)。单击(函数()
{
conn.server.runTest();
});
$(“#cmdReset”)。单击(函数()
{
conn.client.updateList(_);
});
$(“#cmdRunTest”)。单击(函数()
{
var message=“”;
var FROUTSCONTAINING=\u列表
.where(函数(f){返回f.Name.indexOf('r')>=0})
.select(函数(f){返回f.Name});
对于(变量i=0;i
我不确定这是否是我在代码中做错的事情(即,我在错误的顺序中做的事情),或者这是IE bug还是信号器bug。例如,当我在conn.client.updateList JS方法的第一行上设置断点,并将调用堆栈一直跟踪到最顶端时,我发现即使在“data”对象中(在signar receive方法中)的数组也没有我的原型方法。经过以下修改后,它对我来说效果很好:
var fruitsContaining = _list
.where(function (f) { return f.indexOf('r') >= 0 })
.select(function (f) { return f});
where和select实际上在那里,而f.Name没有,因为数组成员是字符串
更新:
好的,忽略上面的内容。以下是修复方法:
var list = list
if (navigator.appName == 'Microsoft Internet Explorer') {
list = Array.prototype.slice.call(_list);
}
var fruitsContaining = list
.where(function (f) { return f.Name.indexOf('r') >= 0 })
.select(function (f) { return f.Name });
for (var i = 0; i < fruitsContaining.length; i++) {
message += " - " + fruitsContaining[i] + "\n";
}
var list=list
如果(navigator.appName==“Microsoft Internet Explorer”){
list=Array.prototype.slice.call(_list);
}
var FROUTSCONTAINING=列表
.where(函数(f){返回f.Name.indexOf('r')>=0})
.select(函数(f){返回f.Name});
对于(变量i=0;i
我不完全理解这个问题,但我相信这可能是jquery中的一个bug。虽然问题有点不同,但我从这个问题中得出了答案:
附加更新
添加了IE检查。我遇到了同样的问题:当我使用Signal r将数组从C#传递到Angular应用程序时,我无法对接收到的对象使用
Array.prototype
中定义的方法。此外,这些对象实际上是“类似于数组”的,因为所描述的一些数组测试将失败。例如,arry instanceof Array
将返回false
,但Array.isArray(arr)
将返回true
当web应用程序托管在IIS中而不支持WebSocket时,问题就开始了。在这种情况下,在Chrome和Firefox中使用serverSentEvents,在internetexplorer和Edge中使用ForeverFrame
,ForeverFrame导致数组反序列化错误。这是因为ForeverFrame使用不同的帧来维护信号器连接,而不同帧中的数组是使用不同的Array
对象创建的
这里有许多解决方案:
$.connection.hub.start()
参数中指定不应使用ForeverFrame,默认为IE和Edge上的LongPollingwindow.JSON
:
$.connection.hub.json = {
parse: function(text, reviver) {
console.log("Parsing JSON");
return window.JSON.parse(text, reviver);
},
stringify: function(value, replacer, space) {
return window.JSON.stringify(value, replacer, space);
}
};
Array.prototype.slice
,将其转换为同一帧的Array
。必须对从SignalR接收的任何阵列执行此操作,因此它不像其他两个选项那样具有可伸缩性你能试试吗;在您的conn.client.updateList()方法中?这个主意很聪明,但是原型方法仍然缺失。实际上.Name就在那里。查看_list的初始化-select方法在数组的每个元素上创建.Name。集线器中的服务器端也会发生同样的情况。每个元素都是一个对象,而不是一个字符串。这就是为什么它在除IE之外的所有浏览器上都能通过Signal工作的原因。甚至当我看着你的时候
var list = list
if (navigator.appName == 'Microsoft Internet Explorer') {
list = Array.prototype.slice.call(_list);
}
var fruitsContaining = list
.where(function (f) { return f.Name.indexOf('r') >= 0 })
.select(function (f) { return f.Name });
for (var i = 0; i < fruitsContaining.length; i++) {
message += " - " + fruitsContaining[i] + "\n";
}
$.connection.hub.json = {
parse: function(text, reviver) {
console.log("Parsing JSON");
return window.JSON.parse(text, reviver);
},
stringify: function(value, replacer, space) {
return window.JSON.stringify(value, replacer, space);
}
};