2012-04-26 74 views
-1

我試圖計算總共有多少項目在我查詢的數據庫中。它是第三方,所以它跨域XMLHttpRequests,但我在Chrome擴展中創建了方法,並且manifest.json中的權限位讓它工作得很好。XMLHttpRequest在返回語句之前未完成調用,因此未定義

我似乎遇到的問題是這樣的:我循環了一個類別列表並計算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); 
} 

,因爲它是爲onreadystateretrieveCategoryCount不會被調用,因爲XMLHttpRequest的仍然是由函數完成的時間待定內的東西。在同步調用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; 
    }); 
} 

這裏的問題是,回調永遠不會運行,因爲該請求仍然是從函數的返回值的時間待定被添加到「總和」。

+1

你的腳本中有太多東西需要修復....你使用jQuery,但只能利用它在幾個小地方的功能 - 有點工作,你至少可以把這個代碼的一半 – ManseUK 2012-04-26 14:48:51

+0

好吧建議將不勝感激。我過去使用過$ .ajax和$ .getJSON,但我已經在擴展中使用了其他類似的代碼,所以我認爲我會保持一致。 – Redrascal 2012-04-26 14:53:03

+0

我可能會建議你通過服務器所有選擇的選項 - 可能是JSON或XML或純文本 - 讓服務器計算總數,只是運行一次屏幕更新 – ManseUK 2012-04-26 14:55:20

回答

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); 
} 
+0

當我嘗試這個時,唯一運行的警報是'alert(「New Sum =」+ sum);'因爲在函數調用的時候請求仍然未決。另外:我對javascript有點新,所以我不會跟着最後的'callback(num);'應該如何解決這個問題。 – Redrascal 2012-04-26 15:48:36

+0

那麼,在這一點上,我相信@ManseUK的ajax答案可能是您在工作方向上的最佳選擇,但是關於回調如何幫助,關鍵是要在所有總計之後放置所有想要運行的代碼已被處理成回調函數。這不是一個特定於JavaScript的事情。基本上,在你原來的代碼中,你調用了異步函數,當它快樂地做它的事情時,你的下一行被執行。您確實希望在異步調用完成之後才能執行下一行。 – brightgarden 2012-04-26 15:54:17

0

傳遞給onreadystatechange回調函數不retrieveCategoryCount。它的返回值丟失,因爲該函數僅在響應readystatechange事件時被調用。

在回調中執行數據所需的操作。不要嘗試返回數據。