Index of an array becomes undefined while looping [duplicate] - javascript

This question already has answers here:
Javascript infamous Loop issue? [duplicate]
(5 answers)
Closed 8 years ago.
I am creating a small domain availability checker. For that I will parse the desired domain into a form, and submit that to a PHP file with jQuery AJAX.
However while I am looping through the different TLD's it suddenly gets undefined and I am not able to use the "TLD" for further processing within the loop. As far as I can read, it as something to do with the loop happening first and the requests made after, so I somehow have to freeze the index of my array. But I don't know how to do that.
This is my code:
$("input[name=submit]").click(function(){
var getDomain = $("#domainsearch").val();
var stripDomain = getDomain.split(".");
var domain = stripDomain[0];
var tlds = ["dk", "se", "com", "net"];
for (var i = 0; i < tlds.length; i++ ) {
var dataString = "domain=" + domain + "." + tlds[i];
console.log(dataString);
$.ajax({
type: "POST",
url: "search.php",
data: dataString,
success: function(data) {
console.log(domain + "." + tlds[i] + " is " + data);
}
});
};
return false;
});
The printed console.log's looks like this:

This is a classic JavaScript issue. In the success function (a closure), the i is being used. That callback runs in the future, once the AJAX call is done. By that point, the loop has finished, and i has been incremented to 4.
tlds[4] doesn't exist, and that's why you're getting undefined. The callbacks are all using the same i value.
To fix it, you need to create a new function to capture the value of i for each callback.
$("input[name=submit]").click(function(){
var getDomain = $("#domainsearch").val();
var stripDomain = getDomain.split(".");
var domain = stripDomain[0];
var tlds = ["dk", "se", "com", "net"];
var createCallback = function(i){
return function(data) {
console.log(domain + "." + tlds[i] + " is " + data);
};
}
for (var i = 0; i < tlds.length; i++ ) {
var dataString = "domain=" + domain + "." + tlds[i];
console.log(dataString);
$.ajax({
type: "POST",
url: "search.php",
data: dataString,
success: createCallback(i)
});
};
return false;
});

By the time the ajax calls return, the loop has long since ended, and i has run past the end of tlds. Trying to print tlds[i] is bound to fail.
Break the lookup into a separate function, with local variables that will be valid on the ajax callback:
var checkup = function(datastring, domain, tld) {
$.ajax({
type: "POST",
url: "search.php",
data: dataString,
success: function(data) {
console.log(domain + "." + tld + " is " + data);
}
});
};
for (var i = 0; i < tlds.length; i++ ) {
var dataString = "domain=" + domain + "." + tlds[i];
console.log(dataString);
checkup(datastring, domain, tlds[i]);
};

You need to enclose the code in your loop in a closure as follows:
$("input[name=submit]").click(function(){
var getDomain = $("#domainsearch").val();
var stripDomain = getDomain.split(".");
var domain = stripDomain[0];
var tlds = ["dk", "se", "com", "net"];
for (var i = 0; i < tlds.length; i++ ) {
(function() {
var dataString = "domain=" + domain + "." + tlds[i];
console.log(dataString);
$.ajax({
type: "POST",
url: "search.php",
data: dataString,
success: function(data) {
console.log(domain + "." + tlds[i] + " is " + data);
}
});
})( i );
}
return false;
});

Related

Rest API Multiple Lists in SharePoint

Because SharePoint works async i cannot store the data from multiple lists in array's and access them later.
I need to use 3 lists because they contain data from employees, holidays, and more.
See my code below for more information.
Is there no easier way to work with SharePoint and multiple lists to get the data. I tried also with executequeryasync but i cannot find a working solution for multiple lists. Or to store the value of each list in an array or variable and use it in another function because it's async.
$(function () {
$('#title').html("Inloggen verlofaanvraag");
});
function inLoggen() {
var initialen = $('#initialen').val();
var wachtwoord = $('#wachtwoord').val();
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Lijst werknemers')/Items?$filter=wInitialen eq '" + initialen + "' and wWachtwoord eq '" + wachtwoord + "'",
type: "GET",
headers: { "accept": "application/json;odata=verbose" },
success: function (data) {
var x = data.d.results;
var werknemers = data.d.results;
for (var i = 0; i < x.length; i++) {
rInitialen = x[i].wInitialen;
rWachtwoord = x[i].wWachtwoord;
rVolledigenaam = x[i].wVolledigenaam;
}
if (i === 0) {
alert("U hebt geen toegang tot deze pagina !");
}
else {
$('#title').html("Welkom " + rVolledigenaam);
$('#inlogform').hide();
persoonlijketellers(werknemers);
}
},
error: function (xhr) {
console.log(xhr.status + ': ' + xhr.statusText);
}
});
}
function persoonlijketellers(werknemers) {
var rId = werknemers[0].ID;
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Lijst persoonlijke tellers')/Items?$filter=pWerknemer eq '" + rId + "'",
type: "GET",
headers: { "accept": "application/json;odata=verbose" },
success: function (data) {
var x = data.d.results;
var ptellers = data.d.results;
for (var i = 0; i < x.length; i++) {
}
wettelijkeverlofdagen(werknemers, ptellers);
},
error: function (xhr) {
console.log(xhr.status + ': ' + xhr.statusText);
}
});
}
function wettelijkeverlofdagen(werknemers, ptellers) {
var rId = ptellers[0].ID;
alert(rId);
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Lijst persoonlijke tellers')/Items?$filter=pWerknemer eq '" + rId + "'",
type: "GET",
headers: { "accept": "application/json;odata=verbose" },
success: function (data) {
var x = data.d.results;
var ptellers = data.d.results;
for (var i = 0; i < x.length; i++) {
}
},
error: function (xhr) {
console.log(xhr.status + ': ' + xhr.statusText);
}
});
}
You can store the data from multiple lists in array and access them when all of your async calls are complete, you just need to use some sort of promise pattern.
jQuery's .when method is probably the most useful in a situation like this:
function SPData() {
function getJsonDataAsync(url) {
// returning the $.ajax object is what makes the next part work...
return $.ajax({
url: url,
method: "GET",
contentType: "application/json",
headers: {
accept: "application/json;odata=verbose"
}
});
}
var requestURI1 = _spPageContextInfo.webServerRelativeUrl + "/_api/lists/..."
var requestURI2 = _spPageContextInfo.webServerRelativeUrl + "/_api/lists/..."
var requestURI3 = _spPageContextInfo.webServerRelativeUrl + "/_api/lists/..."
var req1 = getJsonDataAsync(requestURI1);
var req2 = getJsonDataAsync(requestURI2);
var req3 = getJsonDataAsync(requestURI3);
// now we can do the next line, because req1/2/3 are actually deferreds
// being returned from $.ajax
jQuery.when(req1, req2, req3).done(function(resp1, resp2, resp3) {
/* do something with all of the requests here...
resp1/2/3 correspond to the responses from each call and are each an
array that looks like: [data, statusText, jqXHR], which means that your
data is in resp1[0], resp2[0], etc. */
});
If you want, you can also just assign the returned values to variables in a higher level context, then use individual jQuery deferreds so that you can be sure all of the calls have succeeded before you start working with the data...
...
var x1, x2, x3;
// use the .then(function() { ... }) pattern because we are just returning a
// deferred/promise from $.ajax
getJsonDataAsync(requestURI1).then(function(data) {
x1 = data;
getJsonDataAsync(requestURI2).then(function(data2) {
x2 = data2;
getJsonDataAsync(requestURI3).then(function(data3) {
x3 = data3;
// do something with x1, x2, and x3
});
});
});
}

json read multiply lines as new onces

I have a problem, my app have an issue when reading more than one value, when there are two it returns zero.
Example:
I get:
male:
{"name":"alexanderbb10","pic":"ico/nopic.png"}
{"name":"admin","pic":"ico/nopic.png"}
$.ajax({
type: "GET",
url: "http://p********************************/explore.php?usr="+******************+"&what="+strUser,
dataType: "json",
data: dataString,
success: function(data)
{
$('#explorediv').append('<div id="pic" data-bb-type="item" data-bb-img="' + data.pic + '" data-bb-title="' + data.name + '">' + data.name + '</div>').show('fast');
}
});
But it only shows one result.
How can i make sure it shows all results?
The server side is php
wrapper two object in an array
{male: [{"name":"alexanderbb10","pic":"ico/nopic.png"}, {"name":"admin","pic":"ico/nopic.png"}]}
var result = JSON.parse(xhr.responseText);
for (var i = 0, len = result.male.length; i < len; ++i) {
// result.male[i];
}
your is an invalid JSON:
male: {"name":"alexanderbb10","pic":"ico/nopic.png"} {"name":"admin","pic":"ico/nopic.png"}
if returned data from the ajax request is an array of object, like
[
{"name":"alexanderbb10","pic":"ico/nopic.png"}
{"name":"admin","pic":"ico/nopic.png"}
]
for show all the element inseide of the data you must cicle all the array element, try to change the success function like this:
function(data) {
for(var k in data){
$('#explorediv').append('<div id="pic" data-bb-type="item" data-bb-img="' + data[k].pic + '" data-bb-title="' + data.name + '">' + data[k].name + '</div>').show('fast');
}
}

populated jquery objects show as undefined when passed

In the following script, although the two weather objects are both populated with data in the ajax calls, the updateWeather call shows them both as undefined prior to that line executing. I moved the variable declarations so they would be global but they still both show undefined prior to the updateWeather call. What am I missing? Can I not set up a variable in the ajax success function and then pass it later?
Note: If you want to test this use a different url as this one won't work for you with out my credentials
function getWeatherForecastStationCode() {
var d = new Date();
var parts = d.toString().split(" ");
var dDate = parts[1] + " " + parts[2] + ", " + parts[3];
var ampm;
if (parts[4].split(":")[0] <= 12) {
ampm = "AM";
} else {
ampm = "PM";
}
var dtime = parts[4].split(":")[0] + ":" + parts[4].split(":")[1];
var datetime = dDate + " " + dtime + ampm;
alert(datetime);
var weatherStation = "KPBI"; // get from GetWeatherService.svc
var forecastFields = "&fields=periods.maxTempF%2cperiods.minTempF%2cperiods.vaildTime%2cperiods.weather%2cperiods.icon";
var currentFields = "&fields=ob.tempC%2cob.tempF%2cob.icon%2cplace.name%2cplace.state";
var forecastUrlWeatherStation = 'http://api.aerisapi.com/forecasts/' + weatherStation + '?limit=1&client_id=' + AerisClientId + '&client_secret=' + AerisWeatherApiSecret + forecastFields;
var currentUrlWeatherStation = 'http://api.aerisapi.com/observations/' + weatherStation + '?limit=1&client_id=' + AerisClientId + '&client_secret=' + AerisWeatherApiSecret + currentFields;
$.ajax({
type: "GET",
url: forecastUrlWeatherStation,
dataType: "json",
success: function (json) {
if (json.success === true) {
forecastedWeather = {
weather: json.response[0].periods[0].weather,
maxTemp: json.response[0].periods[0].maxTempF,
minTemp: json.response[0].periods[0].minTempF,
weatherIcon: json.response[0].periods[0].icon,
obsTime: datetime
};
}
else {
alert('An error occurred: ' + json.error.description);
}
}
});
var location;
$.ajax({
type: "GET",
url: currentUrlWeatherStation,
dataType: "json",
success: function (json) {
if (json.success === true) {
var place = json.response.place.name.split(" ");
if (place.length === 1) {
location = place[0].charAt(0).toUpperCase() + place[0].substr(1, place[0].length);
} else {
location = place[0].charAt(0).toUpperCase() + place[0].substr(1, place[0].length) + " " + place[1].charAt(0).toUpperCase() + place[1].substr(1, place[1].length) + ", " + json.response.place.state.toUpperCase();
}
currentWeather = {
location: location,
currentTemp: json.response.ob.tempF
};
} else {
alert('An error occurred: ' + json.error.description);
}
}
});
updateWeather(forecastedWeather,currentWeather);
}
The problem is that AJAX is Asynchronous (Thats the "A" in "AJAX"), so the call to updateWeather is executing before a response is received from your 2 ajax calls.
The way to do this then, is to wait for all ajax calls to complete before calling updateWeather.
Something like the following (untested):
$.when(getForecast(),getCurrent()).done(function(f,c){
updateWeather(forecastedWeather,currentWeather)
});
function getForecast(){
return $.ajax({
type: "GET",
url: forecastUrlWeatherStation,
dataType: "json"
....
});
};
function getCurrent(){
return $.ajax({
type: "GET",
url: currentUrlWeatherStation,
dataType: "json"
....
});
};

Parsing the json data from google and twitter differences

I am new to javascript. I have worked on twitter API. In twitter API i used jQuery.ajax function to get json data from twitter servers. But when i use the same option with google maps server, my app isn't giving any response the moment it enters the jQuery.ajax. I tried to debug it using jslint, but it came out clean. I used debugging using alert, and it stops when it enters jQuery.ajax function. Is meathod to retrieve data varies with the source ?
If not why isn't my code responding ?
Twitter running function ::
var twitterapi = "http://search.twitter.com/search.json?";
jQuery.ajax(
{
type: "GET",
url: twitterapi,
data:
{
"q": hashtag,
"rpp": 1000
},
dataType: 'jsonp'
}).done(function (response)
{
var results = response.results;
for (var i = 0; i < results.length; i++)
{
$("#tweet").prepend("<li class='tweet'>" +
"<img src='" +
results[i].profile_image_url +
"'/>" +
"<span class='username'>" +
results[i].from_user +
"</span> <span class='tweet_content'> " +
results[i].text +
"</span></li>");
}
});
My google maps API(not working)
var j = 2;
var friends = [];
var distance =[];
$(document).ready(function () {
alert("function started");
$('#button').click(function () {
if (j < 11) {
$('#friends').append('Friend' + j + ':<input type="text" id="friend' + j + '"/><br/><br/>');
j++;
}
else {
alert("Limit reached");
}
});
$('button').click(function(){
var a =[];
alert("button clickede");
for(i=1;i<=j;i++)
{
a[i] = $("#friend" + i).val();
}
var gurl = "http://maps.googleapis.com/maps/api/distancematrix/json?"+
"origins=" +
a.join('|').replace(/ /g,'+') +
"&destinations=" +
a.join('|').replace(/ /g,'+') +
"&sensor=false";
alert("making request to" +gurl);
jQuery.ajax(
{
type: "GET",
url: gurl,
dataType: 'jsonp'
}).done(function (response)
{
alert("request made to"+gurl);
var rows = response.rows;
alert(row[0].elements[0].value);
for(var i=0;i<rows.length;i++)
{
for(var j=0;j<elements.length;j++)
{
distance[i][j] = row[i].elements[j].distance.value;
}
}
alert(distance[0][0]);
});
});
});
I don't know what error are you getting so i can't be of much help.
But the code you posted has three issues:
1- Since a is undefined, i couldn't get past the first two lines.
2- Removing the a calls in the code, then it threw a Syntax Error. I fixed this by removing the last }); line.
3- It made the request, but it threw another error (probably because the URL was malformed).

Changing global variables in a ajax call

I've been trying to get this right for quite some time, I'm trying to append the object from the first ajax call after the second ajax call. But the for loop seems to iterate the changing of the value to the last result before appending the information, having the last post appended every time.
var scribjson =
{
"user_id" : localStorage.viewing,
};
scribjs = JSON.stringify(scribjson);
var scrib = {json:scribjs};
$.ajax({
type: "POST",
url: "getScribbles.php",
data: scrib,
success: function(result)
{
var obj = jQuery.parseJSON(result);
for(var i = 0; i < obj.length; i+=1)
{
var userjson =
{
"user_id" : obj[i].user_id
};
userjs = JSON.stringify(userjson);
var user = {json:userjs};
localStorage.post = obj[i].post;
$.ajax({
type: "POST",
url: "getRequestsInfo.php",
data: user,
success: function(result)
{
var obj2 = jQuery.parseJSON(result);
$('#listOfScribbles').append("<tr><td><img id = 'small_pic' src = '" + obj2[0].profileImage + "'/></td><tr><td>" + obj2[0].firstname + " " + obj2[0].lastname + "</td></tr> ");
$('#listOfScribbles').append("<tr><td>" + obj[i].post + "</td></tr>");
},
error: function()
{
alert('An Error has occured, please try again.');
}
});
}
},
error: function()
{
alert('An Error has occured, please try again.');
}
});
Since ajax calls It looks like the all success functions of the inner ajax call are being called after the loop has ended, so i will always be the last iterated value.
Try this:
(function(i)
{
$.ajax({
type: "POST",
url: "getRequestsInfo.php",
data: user,
success: function(result)
{
var obj2 = jQuery.parseJSON(result);
$('#listOfScribbles').append("<tr><td><img id = 'small_pic' src = '" + obj2[0].profileImage + "'/></td><tr><td>" + obj2[0].firstname + " " + obj2[0].lastname + "</td></tr> ");
$('#listOfScribbles').append("<tr><td>" + obj[i].post + "</td></tr>");
},
error: function()
{
alert('An Error has occured, please try again.');
}
});
})(i);
This will create a closure on i, which will give each ajax call its own copy of the current value.
Use an IIFE:
success: (function(i){return function(result) {
var obj2 = jQuery.parseJSON(result);
$('#listOfScribbles').append("<tr><td><img id = 'small_pic' src = '" + obj2[0].profileImage + "'/></td><tr><td>" + obj2[0].firstname + " " + obj2[0].lastname + "</td></tr> ");
$('#listOfScribbles').append("<tr><td>" + obj[i].post + "</td></tr>");
}})(i),
etc. Currently your loop generated ajax success handlers contain a direct reference to the counter itself, which (by the time they are called) has reached its final value.

Categories