JavaScript ajax call inside another ajax call - javascript

I’ve got a call that brings up an url id for a recipe, that I’m trying feed into another call to return additional recipe data, but I think the scope is incorrect somewhere.
I’m getting
Cannot read property 'id' of undefined at XMLHttpRequest.http.onreadystatechange
in Chrome.
function searchFood() {
var http = new XMLHttpRequest();
var foodID = 'a1e1c125';
var foodApiKey = 'c84a720e4f1750b59ce036329fccdc00';
var foodMethod = 'GET';
var url = 'http://api.yummly.com/v1/api/recipes?_app_id=' + foodID + '&_app_key=' + foodApiKey + '&q=scandinavian';
http.open(foodMethod, url);
http.onreadystatechange = function() {
if (http.readyState == XMLHttpRequest.DONE && http.status === 200) {
var foodData = JSON.parse(http.responseText);
var foodName = foodData.matches[0].recipeName;
console.log(foodData);
for (var i = 0; foodData.matches.length; i++) {
var recipeId = foodData.matches[i].id;
console.log(recipeId);
}
function getRecipe() {
var http = new XMLHttpRequest();
var foodID = 'a1e1c125';
var foodApiKey = 'c84a720e4f1750b59ce036329fccdc00';
var foodMethod = 'GET';
var url = 'http://api.yummly.com/v1/api/recipe/' + recipeId + '?_app_id=' + foodID + '&_app_key=' + foodApiKey;
http.open(foodMethod, url);
http.onreadystatechange = function() {
if (http.readyState == XMLHttpRequest.DONE && http.status === 200) {
var data = JSON.parse(http.responseText);
console.log(data);
} else if (http.readyState === XMLHttpRequest.DONE) {
alert("something went wrong");
}
};
http.send();
};
} else if (http.readyState === XMLHttpRequest.DONE) {
alert('Something went wrong')
}
};
http.send();
};
Any tips would be appreciated, thanks

Your truthy check is always true
for (var i = 0; foodData.matches.length; i++)
you are missing i<

Related

Can't get all JSON to show up

It will always display the "cretetion" associated link JSON as the others are overwritten. So I tried incrementing to get all of them, but it didn't work. I don't know what I am doing wrong.
var users = ["ESL_SC2", "OgamingSC2", "cretetion"];
function loadXMLDoc() {
var xmlhttp = new XMLHttpRequest();
for (var i = 0; i < users.length ; i++) {
var url = "https://wind-bow.glitch.me/twitch-api/streams/" + users[i];
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE ) {
if (xmlhttp.status == 200) {
document.getElementById('online-id').innerHTML += (xmlhttp.responseText + "<br />");
}else if (xmlhttp.status == 400) {
console.log('There was an error 400');
}else {
console.log('Something else other than 200 was returned.');
}
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
}
var onlineButton = document.getElementById('online-button-id');
onlineButton.addEventListener('click', loadXMLDoc, false);
I've fixed your code here:
https://plnkr.co/edit/VbkKc9QuVALAYLpujSdo?p=preview
First, the callback xmlhttp.onreadystatechange is overwritten every iteration of the loop so only the last element will be handled.
you should create and manage the XMLHttp object inside the loop, one for each element of your user array.
Secondy and most important you must wrap xmlhttp.onreadystatechange inside an Immediate invoked function otherwise each callback will use the last xmlhttp object then you will be getting the last result all the time, as you were saying above.
for (var i = 0; i < users.length ; i++) {
var xmlhttp = new XMLHttpRequest();
var url = "https://wind-bow.glitch.me/twitch-api/streams/" + users[i];
(function(xmlhttp){
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE ) {
if (xmlhttp.status == 200) {
document.getElementById('online-id').innerHTML += (xmlhttp.responseText + "<br/><br/>");
}else if (xmlhttp.status == 400) {
console.log('There was an error 400');
}else {
console.log('Something else other than 200 was returned.');
}
}
}
})(xmlhttp)
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
Try creating a new XMLHttpRequest for each iteration of the loop instead of re-using the same one. i.e.
function loadXMLDoc() {
for (var i = 0; i < users.length ; i++) {
var xmlhttp = new XMLHttpRequest();
...

Maintaining state of variables when changed inside a timer

I am using JavaScript.
I amusing a setInterval timer method.
Inside that method I am changing the values of module variables.
The thing is in IE the changes to the variables are not 'saved'. But in Chrome they are.
What is the accepted practice to do what I need to do?
this is my code:
function start()
{
var myVar = setInterval(function () { GetTimings() }, 100);
}
var currentts1;
var currentts2;
var currentts3;
var currentts4;
var frameCounter;
function GetTimings() {
if (frameCounter < 1) {
frameCounter++;
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", urlTS, false);
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4) {
var nextts = xmlhttp.responseText;
var bits = nextts.split('|');
if (currentts1 != bits[0]) {
currentts1 = bits[0];
postMessage("0|" + bits[0]);
}
if (currentts2 != bits[1]) {
currentts2 = bits[1];
postMessage("1|" + bits[1]);
}
if (currentts3 != bits[2]) {
currentts3 = bits[2];
postMessage("2|" + bits[2]);
}
if (currentts4 != bits[3]) {
currentts4 = bits[3];
postMessage("3|" + bits[3]);
}
frameCounter--;
}
}
xmlhttp.send();
}
}
The variables:
currentts1
currentts2
currentts3
currentts4
frameCounter
values are not preserved...
Try this, but notice I changed the currentts* to an Array when you try to view them
function start() {
var myVar = setInterval(GetTimings, 100);
}
var currentts = [null, null, null, null];
var in_progress = 0; // clear name
function GetTimings() {
var xhr;
if (in_progress > 0) return; // die
++in_progress;
xhr = new XMLHttpRequest();
xhr.open('GET', urlTS);
function ready() {
var nextts = this.responseText,
bits = nextts.split('|'),
i;
for (i = 0; i < currentts.length; ++i)
if (currentts[i] !== bits[i])
currentts[i] = bits[i], postMessage(i + '|' + bits[i]);
--in_progress;
}
if ('onload' in xhr) // modern browser
xhr.addEventListener('load', ready);
else // ancient browser
xhr.onreadystatechange = function () {
if (this.readyState === 4 && xhr.status === 200)
ready.call(this);
};
// listen for error, too?
// begin request
xhr.send();
}

send multiple ajax call to a same file

I have a big table and my idea to optimize my program is to get the information one by one and update the table as the information arrives.
To do that I am using an ajax call to a php file which collect the data from the database. I am trying to send and receive the data one by one:
for (var i = depF; i <= depT; i++) {
xmlhttp.open("GET", "../../php_includes/reports/InventoryReportPage.php?date=" + arguments[0] + "&depF=" + i + "&depT=" + i + "&subT=" + subT + "&subF=" + subF + "&catT=" + catT
+ "&catF=" + catF + "&Tar=" + Tar, true);
xmlhttp.send();
console.log("sent ajax");
}
this code will correctly send 2 ajax calls (in the browser I can see two "sent ajax"). However in the receiver:
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState === 4 && xmlhttp.status === 200)
{
console.log("recieved");
if (xmlhttp.responseText) {
var table = document.getElementById("inventoryReport");
table.innerHTML += xmlhttp.responseText;
}
}
}
I only see one return value. Any idea if I am even allowed to use ajax calls like this?
The whole function:
var isClicked = false;
function onClick(date, depF, depT, subF, subT, catT, catF, Tar) {
//alert(date+ depF+ depT+ subF+ subT+ catT+ catF+ Tar)
// return null;
if (!isClicked) {
console.log("in the function");
var clicked = arguments[0];
isClicked = true;
var div = clicked + "apDiv";
var browserSupport = (navigator.userAgent.indexOf('Firefox') != -1) || ((navigator.userAgent.indexOf('Chrome') != -1) || (navigator.userAgent.indexOf('Safari') != -1));
if (browserSupport) {
var xmlhttp = new XMLHttpRequest();
}
else {
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
if (!xmlhttp) {
alert("your browser doens't supposrt XMLHTTP " + navigator.userAgent);
}
xmlhttp.onreadystatechange = function()
{
if (xmlhttp.readyState === 4 && xmlhttp.status === 200)
{
console.log("recieved: "+xmlhttp.responseText);
if (xmlhttp.responseText) {
var table = document.getElementById("inventoryReport");
table.innerHTML += xmlhttp.responseText;
}
}
}
for (var i = depF; i <= depT; i++) {
xmlhttp.open("GET", "../../php_includes/reports/InventoryReportPage.php?date=" + arguments[0] + "&depF=" + arguments[1] + "&depT=" + arguments[2] + "&subT=" + subT + "&subF=" + subF + "&catT=" + catT
+ "&catF=" + catF + "&Tar=" + Tar, true);
xmlhttp.send();
console.log("sent the ajax");
}
}
}
The reason your code don't work as you expect is that you basically overwrite the requests you are doing. You can try something like this:
var reqs = [];
for (var i = depF; i <= depT; i++) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "/", true);
xmlhttp.send();
reqs.push(xmlhttp);
}
reqs.forEach(function(req) {
req.onreadystatechange = function()
{
if (req.readyState === 4 && req.status === 200)
{
console.log("recieved");
if (req.responseText) {
var table = document.getElementById("inventoryReport");
table.innerHTML += req.responseText;
}
}
}
})

XMLHttpRequest loop memory leak

I'm trying to check many items against information on ajax URL. But when I'm running this function in browser, memory usage goes above 2 gigs and then browser crashes (Chrome, Firefox). What am I doing wrong? items variable is really big - >200 000 and also includes some large strings.
var items = [1,2,3,4,5,6,7,8,9,10,...,300000]
var activeItems = {}
function loopAjax(){
for (i=0; i < items.length; i++) {
var currItem = items[i];
var request = new XMLHttpRequest();
var found = 0
request.open("GET", "/item=" + currItem);
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
var response = JSON.parse(request.responseText);
var active = response[0].active;
if (active) {
console.log("FOUND ACTIVE! " + currItem);
activeItems[found] = {"active": true, "item": currItem};
found++;
}
}
}
request.send();
}
}
Thank goodness the browser stalls and dies. If it didn't you just created a denial of service attack!
The problem needs to be reapproached. You better off creating a state machine which has a stack of requests in it. That way you only doing say 5 concurrent requests at a time.
function ItemChecker(sample_size, max_threads) {
this.sample_size = sample_size;
this.max_threads = max_threads;
this.counter = 0;
this.activeItems = [];
this.isRunning = false;
this.running_count = 0;
}
ItemChecker.prototype.start = function start() {
this.isRunning = true;
while (this.running_count < this.max_threads) {
this.next();
}
return this;
};
ItemChecker.prototype.stop = fucntion stop() {
this.isRunning = false;
return this;
};
ItemChecker.prototype.next = function next() {
var request, item_id, _this = this;
function xhrFinished(req) {
var response;
if (req.readyState !== 4) {
return;
}
_this.counter--;
if (req.status === 200) {
try {
response = JSON.parse(request.responseText);
if (response[0].active) {
_this.activeItems.push({
active: true,
item: item_id;
});
}
} catch(e) {
console.error(e);
}
// When finished call a callback
if (_this.onDone && _this.counter >= _this.sample_size) {
_this.onDone(_this.activeItems);
}
}
else {
console.warn("Server returned " + req.status);
}
}
if (!this.isRunning || this.counter >= this.sample_size) {
return;
}
item_id = this.counter;
this.counter++;
request = new XMLHttpRequest();
request.onreadystatechange = xhrFinished;
request.open("GET", "item=" + item_id);
request.send();
};
ItemChecker.prototype.whenDone = function whenDone(callback) {
this.onDone = callback;
return this;
};
This might work? Didn't try it for real. But you would call it with:
var item_checker = new ItemChecker(300000, 5);
item_checker.whenDone(function(active) {
// Do something with active
}).start();

Javascript / ajax code - works in chrome and firefox but not in IE10

What I'm trying to do is limit the options of one select box based on what the user chooses in a prior select box. It works perfectly in Chrome and Firefox, but in IE 10 the only thing that shows up is the text "Not Found". I'm not sure, but my guess is that something is going wrong in request.status. What it is, however, I have no idea.
function prepForms() {
for (var i = 0; i<document.forms.length; i++) {
var thisform = document.forms[i];
var departCity = document.getElementById("departcity");
departCity.onchange = function() {
var new_content = document.getElementById("ajaxArrive");
if (submitFormWithAjax(thisform, new_content)) return false;
return true;
}
}
}
function getHTTPObject() {
if (typeof XMLHttpRequest == "undefined")
XMLHttpRequest = function() {
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
catch (e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
catch (e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); }
catch (e) {}
return false;
}
return new XMLHttpRequest();
}
function submitFormWithAjax(whichform, thetarget) {
var request = getHTTPObject();
if (!request) {return false;}
var dataParts = [];
var element;
for (var i = 0; i<whichform.elements.length; i++) {
element = whichform.elements[i];
dataParts[i] = element.name + "=" + encodeURIComponent(element.value);
}
var data = dataParts.join("&");
request.open("POST", "flightlocationfilter.asp#ajaxArrive", true);
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
request.onreadystatechange = function() {
if (request.readyState == 4) {
if (request.status == 200 || request.status == 0) {
var matches = request.responseText.match(/<div id="ajaxArrive">([\s\S]+)<\/div>/);
if (matches.length > 0) {
thetarget.innerHTML = matches[1];
} else {
thetarget.innerHTML = "<p>--Error--</p>";
}
} else {
thetarget.innerHTML = "<p>" + request.statusText + "</p>";
}
}
};
request.send(data);
return true;
};
Edit: After walking through with the IE Developer Tools, it looks like the request.readyState is not moving beyond 1 to 4.

Categories