{"id":487,"date":"2022-08-30T15:02:10","date_gmt":"2022-08-30T15:02:10","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2013\/11\/09\/xmlhttprequest-calls-not-finishing-before-return-statement-so-undefined-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:02:10","modified_gmt":"2022-08-30T15:02:10","slug":"xmlhttprequest-calls-not-finishing-before-return-statement-so-undefined-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2022\/08\/30\/xmlhttprequest-calls-not-finishing-before-return-statement-so-undefined-collection-of-common-programming-errors\/","title":{"rendered":"XMLHttpRequest calls not finishing before return statement so undefined-Collection of common programming errors"},"content":{"rendered":"<p>I&#8217;m attempting to count how many items total are in the database I&#8217;m querying. It&#8217;s third party so it&#8217;s cross domain XMLHttpRequests but I&#8217;m making the method in a Chrome Extension and the permissions bit in the manifest.json let&#8217;s it work nicely.<\/p>\n<p>The problem I seem to be having is this: I&#8217;m looping through a list of categories and counting the amount in each before the XMLHttpRequests are coming back from the external server. The methods are started by the press of a button of id=&#8221;countButton&#8221;. Here&#8217;s the relevant javascript\/jQuery:<\/p>\n<pre><code>\/\/simple listener for the button\ndocument.getElementById('countButton').addEventListener('click', function() runTotalCount()}, true);\n\n\/\/loops through a list of categories in a drop down with values 0-36\nfunction runTotalCount(){\n    var sum = 0;\n    $('#categorySelect option').each(function(){\n        var value = $(this).val();\n        sum += retrieveCategoryCount(value);\n        alert(\"New Sum = \" + sum);\n    });\n    var total = \"<br \/>Total items in Sum is \" + sum + \"<br \/><br \/>\";\n    document.getElementById('results').innerHTML = total;\n}\n\n\/\/actually makes the request and sums the items count for each category\n\/\/the server response is a json with an alphabetized \"items\" per category\nfunction retrieveCategoryCount(num){\n    var sum = 0;\n    var xhr = new XMLHttpRequest();\n    xhr.onreadystatechange = function(){\n        if (xhr.readyState == 4 &amp;&amp; xhr.status == 200){\n            var str = xhr.responseText;\n            alert(\"str = \" + str);\n            var json = $.parseJSON(str);\n            alert(\"JSON = \" + json);\n            for(item in json.alpha){\n                alert(\"items count = \" + json.alpha[item].items);\n                sum += json.alpha[item].items;\n            }\n        alert(\"Category Sum = \" + sum);\n        return sum;\n        }\n    }\n    xhr.open(\n        \"GET\",\n        \"http:\/\/services.runescape.com\/m=itemdb_rs\/api\/catalogue\/category.json?category=\" + num,\n        true);\n    xhr.send(null);\n}\n<\/code><\/pre>\n<p>As it is the stuff within the <code>onreadystate<\/code> for <code>retrieveCategoryCount<\/code> never gets called because the XMLHttpRequests are still pending by the time the function finishes. On synchronous calls the <code>alert(\"Category Sum = \" + sum);<\/code> returns the right number but then the function return just below it is NaN (I&#8217;d rather not hang up the browser though so asynchronous is what I&#8217;d prefer for a solution).<\/p>\n<p>What needs to change to properly get the item count? Thanks in advance.<\/p>\n<p>UPDATE: I&#8217;ve also tried code for <code>retrieveCategoryCount<\/code> of this:<\/p>\n<pre><code>function retrieveCategoryCount(num){\n    var sum = 0;\n    $.getJSON(\"http:\/\/services.runescape.com\/m=itemdb_rs\/api\/catalogue\/category.json?category=\" + num, function(data){\n        for(item in data.alpha){\n            alert(\"items count = \" + data.alpha[item].items);\n            sum += data.alpha[item].items;\n        }\n    alert(\"Category Sum = \" + sum);\n    return sum;\n    });\n}\n<\/code><\/pre>\n<p>The problem here is that the callback never gets run because the request is still pending by the time the value returned from the function is added to &#8220;sum&#8221;.<\/p>\n<ol>\n<li>\n<p>You can put the code that should happen AFTER the async call completes into a callback function and pass that into your async function, then have it callback.<\/p>\n<pre><code>var sum = 0,\n    setTotalCount = function(data){ \n        .. stuff to set the dom element based on callback\n    };\n$('#categorySelect option').each(function(){\n    var value = $(this).val();\n    retrieveCategoryCount(value, setTotalCount);\n});\n\n\nfunction retrieveCategoryCount(num, callback){\nvar sum = 0;\nvar xhr = new XMLHttpRequest();\nxhr.onreadystatechange = function(){\n    if (xhr.readyState == 4 &amp;&amp; xhr.status == 200){\n        var str = xhr.responseText;\n        alert(\"str = \" + str);\n        var json = $.parseJSON(str);\n        alert(\"JSON = \" + json);\n        for(item in json.alpha){\n            alert(\"items count = \" + json.alpha[item].items);\n            sum += json.alpha[item].items;\n        }\n    alert(\"Category Sum = \" + sum);\n       callback(sum); \/\/ callback the function you passed in\n    }\n}\nxhr.open(\n    \"GET\",\n    \"http:\/\/services.runescape.com\/m=itemdb_rs\/api\/catalogue\/category.json?category=\" + num,\n    true);\nxhr.send(null);\n}\n<\/code><\/pre>\n<\/li>\n<li>\n<p>The callback function you pass to <code>onreadystatechange<\/code> is not <code>retrieveCategoryCount<\/code>. It&#8217;s return value is lost because the function is only called in response to the readystatechange event.<\/p>\n<p>Do what you need to do with the data <strong>in the callback<\/strong>. Don&#8217;t try to return the data.<\/p>\n<\/li>\n<\/ol>\n<p id=\"rop\"><small>Originally posted 2013-11-09 19:45:38. <\/small><\/p>","protected":false},"excerpt":{"rendered":"<p>I&#8217;m attempting to count how many items total are in the database I&#8217;m querying. It&#8217;s third party so it&#8217;s cross domain XMLHttpRequests but I&#8217;m making the method in a Chrome Extension and the permissions bit in the manifest.json let&#8217;s it work nicely. The problem I seem to be having is this: I&#8217;m looping through a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-487","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/487","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=487"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/487\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=487"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=487"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=487"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}