-1

クエリを実行しているデータベースに含まれるアイテムの合計数を数えようとしています。これはサード パーティなので、クロス ドメインの XMLHttpRequests ですが、Chrome 拡張機能でメソッドを作成しており、manifest.json のアクセス許可ビットでうまく機能します。

私が抱えていると思われる問題は次のとおりです。XMLHttpRequests が外部サーバーから返される前に、カテゴリのリストをループしてそれぞれの量を数えています。メソッドは、id="countButton" のボタンを押すことによって開始されます。関連する javascript/jQuery は次のとおりです。

//simple listener for the button
document.getElementById('countButton').addEventListener('click', function() runTotalCount()}, true);

//loops through a list of categories in a drop down with values 0-36
function runTotalCount(){
    var sum = 0;
    $('#categorySelect option').each(function(){
        var value = $(this).val();
        sum += retrieveCategoryCount(value);
        alert("New Sum = " + sum);
    });
    var total = "<p>Total items in Sum is " + sum + "</p>";
    document.getElementById('results').innerHTML = total;
}

//actually makes the request and sums the items count for each category
//the server response is a json with an alphabetized "items" per category
function retrieveCategoryCount(num){
    var sum = 0;
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
        if (xhr.readyState == 4 && xhr.status == 200){
            var str = xhr.responseText;
            alert("str = " + str);
            var json = $.parseJSON(str);
            alert("JSON = " + json);
            for(item in json.alpha){
                alert("items count = " + json.alpha[item].items);
                sum += json.alpha[item].items;
            }
        alert("Category Sum = " + sum);
        return sum;
        }
    }
    xhr.open(
        "GET",
        "http://services.runescape.com/m=itemdb_rs/api/catalogue/category.json?category=" + num,
        true);
    xhr.send(null);
}

onreadystate関数が終了するまで XMLHttpRequests がまだ保留中であるため、 for内のものはretrieveCategoryCount決して呼び出されません。同期呼び出しでalert("Category Sum = " + sum);は、正しい数値が返されますが、関数はそのすぐ下に NaN を返します (ブラウザーをハングアップさせたくないので、解決策として非同期が望ましいです)。

アイテム数を適切に取得するには、何を変更する必要がありますか? 前もって感謝します。

更新:これのコードも試しましretrieveCategoryCountた:

function retrieveCategoryCount(num){
    var sum = 0;
    $.getJSON("http://services.runescape.com/m=itemdb_rs/api/catalogue/category.json?category=" + num, function(data){
        for(item in data.alpha){
            alert("items count = " + data.alpha[item].items);
            sum += data.alpha[item].items;
        }
    alert("Category Sum = " + sum);
    return sum;
    });
}

ここでの問題は、関数から返された値が「sum」に追加されるまでにリクエストがまだ保留されているため、コールバックが実行されないことです。

4

2 に答える 2

0

非同期呼び出しが完了した後に発生するコードをコールバック関数に入れ、それを非同期関数に渡し、それをコールバックさせることができます。

var sum = 0,
    setTotalCount = function(data){ 
        .. stuff to set the dom element based on callback
    };
$('#categorySelect option').each(function(){
    var value = $(this).val();
    retrieveCategoryCount(value, setTotalCount);
});


function retrieveCategoryCount(num, callback){
var sum = 0;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
    if (xhr.readyState == 4 && xhr.status == 200){
        var str = xhr.responseText;
        alert("str = " + str);
        var json = $.parseJSON(str);
        alert("JSON = " + json);
        for(item in json.alpha){
            alert("items count = " + json.alpha[item].items);
            sum += json.alpha[item].items;
        }
    alert("Category Sum = " + sum);
       callback(sum); // callback the function you passed in
    }
}
xhr.open(
    "GET",
    "http://services.runescape.com/m=itemdb_rs/api/catalogue/category.json?category=" + num,
    true);
xhr.send(null);
}
于 2012-04-26T14:55:11.053 に答える
0

渡すコールバック関数onreadystatechangeは notretrieveCategoryCountです。関数は readystatechange イベントに応答してのみ呼び出されるため、戻り値は失われます。

callback 内のデータに対して必要なことを行います。データを返そうとしないでください。

于 2012-04-26T14:56:40.713 に答える