5

プロトタイプ メソッド (この場合は Array.prototype メソッド) が IE でのみ消失し、配列が SignalR を通過する場合にのみ問題が発生しました。

私は、この問題を示す小さい/愚かだが単純な概念実証 Web アプリを作成しました (コードはすべて以下にあります)。[すべてのクライアントを更新] をクリックしてから [文字 'r' を含む果物] をクリックすると、_list のプロトタイプ メソッドが見つからず、例外が発生することに注意してください。その場合、配列は SignalR から取得されました。「リセット」をクリックして配列をハードコードされた値にリセットすると、「文字 'r' を含む果物」ボタンが突然機能します - プロトタイプ メソッドが戻ってきました。この問題は IE でのみ発生することに注意してください。

ヒント: 最初に概念実証を書いたとき、問題を再現できませんでした。配列がSignalRを介して取得されたとき、IEにはまだプロトタイプメソッドがありましたが、ページが読み込まれたときに別のエラーが発生しました。誤ってjQueryを2回含めていました。冗長なスクリプトを取り出して 2 番目の jQuery を含めると、(明らかに) そのエラーは修正されましたが、問題を再現できるようになりました。IE には、私が作成した Array プロトタイプ メソッドがありませんでしたが、配列が SignalR 経由で提供された場合のみでした。

myExtensions.js:

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;
}

_Layout.cshtml

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@ViewBag.Title - My ASP.NET MVC Application</title>
        <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
        <meta name="viewport" content="width=device-width" />

        @Styles.Render("~/Content/css")

        @Scripts.Render("~/Scripts/myExtensions.js")
        @Scripts.Render("~/bundles/modernizr")
        @Scripts.Render("~/Scripts/jquery-1.7.1.js")
        @Scripts.Render("~/Scripts/jquery.signalR-1.0.0-rc1.js")
        <script src="~/signalr/hubs"></script>

    </head>
    <body>
        <header>
            <div class="content-wrapper">
                <div class="float-left">
                    <p class="site-title">@Html.ActionLink("IE/SignalR error POC", "Index", "Home")</p>
                </div>
            </div>
        </header>
        <div id="body">
            @RenderSection("featured", required: false)
            <section class="content-wrapper main-content clear-fix">
                @RenderBody()
            </section>
        </div>
        <footer>
            <div class="content-wrapper">
                <div class="float-left">
                    <p>&copy; @DateTime.Now.Year - My ASP.NET MVC Application</p>
                </div>
            </div>
        </footer>
        @*@Scripts.Render("~/Scripts/myExtensions.js")*@
    </body>
</html>

ListHub.cs

using System.Linq;
using Microsoft.AspNet.SignalR.Hubs;

namespace SignalR_Bug_POC.Hubs
{
    public class ListHub : Hub
    {
        public void RunTest()
        {
            Clients.All.updateList(new string[]
                {
                    "apple", "pear", "grape", "strawberry", "rasberry", "orange", "watermelon"
                }.Select(f => new { Name = f }).ToList());
        }
    }
}

インデックス.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>

それがコードで間違っているのか (つまり、間違った順序で実行しているのか)、それとも IE のバグなのか SignalR のバグなのかはわかりません。たとえば、conn.client.updateList JS メソッドの最初の行にブレークポイントを設定し、コール スタックを一番上まで追跡すると、(SignalR receive メソッド内に) 'data' オブジェクトの配列が存在しないことがわかります。私のプロトタイプメソッドがありません。

4

2 に答える 2

0

次の変更により、私にとっては問題なく動作します。

var fruitsContaining = _list
    .where(function (f) { return f.indexOf('r') >= 0 })
    .select(function (f) { return f});

where と select は実際にはありましたが、配列メンバーが文字列であるため、そうではありませんでした。

アップデート:

わかりました、上記は無視してください。修正は次のとおりです。

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";
}

問題を完全には理解していませんが、jquery のバグである可能性があります。質問は少し異なりますが、この質問から解決策を盗みました: なぜ配列プロトタイプへのこの変更が jQuery プラグインで機能しないのですか?

追加の更新

IE チェックを追加しました。

于 2012-12-28T14:10:22.330 に答える