XMLHttpRequest调用未在return语句之前完成,因此未定义

时间:2012-04-26 14:46:20

标签: javascript jquery google-chrome-extension xmlhttprequest

我正在尝试计算我正在查询的数据库中有多少项目。它是第三方,因此它是跨域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 retrieveCategoryCount中的内容永远不会被调用,因为XMLHttpRequests在函数完成时仍处于未决状态。在同步调用中,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”时,请求仍处于挂起状态。

2 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:0)

您传递给onreadystatechange的回调函数不是retrieveCategoryCount。它的返回值丢失,因为只响应readystatechange事件调用该函数。

执行回调中数据所需的操作。不要试图返回数据。