-2

こんにちは、次の値を5秒ごとに表示したいjson配列があります

このコードは、サーバーから json を取得し、json 配列を関数に送信します。

function myFunction() {
        $.ajax({
            type: "POST",
            url: "ws.aspx/GetQueue",
            data: "{'eventid':'" + eventID + "'}",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (msg) {
                if (msg != null) {
                    var obj;
                    if (msg.hasOwnProperty("d"))
                        obj = jQuery.parseJSON(msg.d);
                    else
                        obj = jQuery.parseJSON(msg);

                    setHtml(obj);
                }

                setTimeout(function () { myFunction(); }, 5000);
            },
            error: function (xhr, ajaxOptions, thrownError) {
                alert(xhr.responseText);

                setTimeout(function () { myFunction(); }, 5000);
            }
        });
    }

これは、配列を送信した後の私の関数です:

function setHtml(obj) {
        for (var i = 0; i < obj.length; i++)
            setTimeout(function () {  $('.Summary').html("<H1>" + obj[i].QueueName + "->" + obj[i].name + ' : ' + obj[i].Queue + "</H1><br/>"); }, 5000);
    }

しかし、ループ内の値は未定義です。なぜですか? この問題の解決策は何ですか?

4

5 に答える 5

1

問題は、setTimeout関数が呼び出されるまでに の値iが変更されていることです。 i常にありobj.lengthobj[obj.length]常にありますundefined。代わりに、Array.forEach()orを使用$.each()して配列を繰り返します。

function setHtml(obj) {
    $.each(obj, function(i, val) {
        setTimeout(function () {
            $('.Summary').html("<H1>" + val.QueueName + "->" + val.name + ' : ' + val.Queue + "</H1><br/>");
        }, 5000);
    });
}

setTimeoutこれにより、変数が変更されないように、コードが独自のスコープにラップされます。

または、呼び出しをsetTimeout独自の関数に入れます。

function setHtml(obj) {
    for (var i = 0; i < obj.length; i++) {
        setSummaryHtml(obj[i]);
    }
}
function setSummaryHtml(val) {
    setTimeout(function () {
        $('.Summary').html("<H1>" + val.QueueName + "->" + val.name + ' : ' + val.Queue + "</H1><br/>");
    }, 5000);
}
于 2013-01-30T16:57:09.920 に答える
1

ループを無名関数内に移動します。

function setHtml(obj) {        
    setTimeout(function () {  
        for (var i = 0; i < obj.length; i++)
            $('.Summary').html("<H1>" + obj[i].QueueName + "->" + obj[i].name + ' : ' + obj[i].Queue + "</H1><br/>"); 
    }, 5000);
}

次に、javascript クロージャについて読んでください。あなたのバージョンでは、 の値はi、外部関数 ( setHtml) を離れるときの値でした。これはobj.lengthです。

于 2013-01-30T16:50:35.117 に答える
1

これは、setTimeout の実行時にの値iが等しくなるためです。obj.length

function setHtml(obj) {
    for (var i = 0; i < obj.length; i++) {
        (function(cObj){
            setTimeout(function () {  $('.Summary').html("<H1>" + cObj.QueueName + "->" + cObj.name + ' : ' + cObj.Queue + "</H1><br/>"); }, 5000);
        })(obj[i]);
    }
}
于 2013-01-30T16:52:04.067 に答える
0

ありがとう、ループ内のjson値を処理するためのwirey以外はすべて答えです。完全な答えは、次のコードのようにキューに要素を追加することです:

$.each(obj, function (i, val) {                                
                        $('.Summary').delay(5000).queue(function (n) {
                                str = "<H1>" + val.QueueName + "->" + val.name + ' : ' + val.Queue + "</H1><br/>";
                                console.log(str);
                                $(this).html(str);
                                n();
                            });
                    });
于 2013-01-31T07:15:46.453 に答える
0

JSON.parseJSONdatatype:jsonを実行する必要はありません。datatype:json に設定すると、javascript オブジェクトが返されるので、

if (msg.hasOwnProperty("d"))
         obj = jQuery.parseJSON(msg.d);
 else
         obj = jQuery.parseJSON(msg);

これだけでもいい

if (msg.hasOwnProperty("d"))
         obj = msg.d;
 else
         obj = msg;

また、 setTimeout 関数でループするにはクロージャーが必要です

for (var i = 0; i < obj.length; i++) {
  (function (ii) {
    setTimeout(function () {
      $('.Summary').html("<H1>" + obj[ii].QueueName + "->" + obj[ii].name + ' : ' + obj[ii].Queue + "</H1><br/>");
    }, 5000);
  })(i);
}
于 2013-01-30T16:50:47.130 に答える