This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I have an array which contains objects, which contains an array, which contains objects. It's a little messy, but this is just the way the Google Books API returns information.
var myList = [
{kind:'book', totalItems:1, items: [{volumeInfo:{authors:['JRR Tolkien']},publishedDate:"1965",pageCount:355}]},
{kind:'book', totalItems:1, items: [{volumeInfo:{authors:['HP Lovecraft']},publishedDate:"1930",pageCount:269}]},
{kind:'book', totalItems:1, items: [{volumeInfo:{authors:['Oscar Wilde']},publishedDate:"1920",pageCount:400}]},
];
console.log(myList);
console.log(myList[1].items[0].pageCount);
I can access everything in here with no problems. When I create an identical array, except using an ajax call in jQuery, I can't access any of the objects or array items.
var bookList = $(".book").map(function () {
return this.id;
}).get();
console.log(bookList);
var thelink = "https://www.googleapis.com/books/v1/volumes?q=isbn:";
var allresults = [];
for (var i = 0; i < bookList.length; i++) {
$.ajax({
url: thelink + bookList[i],
dataType: 'json',
type: 'get',
cache: true,
success: function (data) {
allresults.push(data);
}
});
};
console.log(allresults[1].items[0].pageCount);
<!doctype html>
<html>
<head>
<title>Google Books</title>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<h1>Input</h1>
<div id="book-container">
<div id="0618249060" class="book"></div>
<div id="9780743258074" class="book"></div>
<div id="9780345466457" class="book"></div>
</div>
<h1>Result</h1>
<div id="resultContainer">
<!--Put a bunch of stuff here-->
</div>
</body>
</html>
As I understand these should be accessible in the exact same way. My only clue is that in the console the variables 'myList' and 'allresults' show up slightly differently. The second one being accessible, the first not.
I'm very confused and have idea what to search to find a solution! What on earth am I doing wrong? Thank you!
This is because ajax calls are asynchronous. So when for loop is finished, you have a console statement which is being executed but until that time, the ajax calls are not finished and hence you cannot access data correctly. Either you should pass a callback and in that callback you should have console or use axios js( promise based HTTP library)
move the line console.log(allresults[1].items[0].pageCount); inside the success callback. It didn't work because ajax is asynchronous and because of that your console.log is diplayed before the ajax call is finish.
your code should be something like:
var thelink = "https://www.googleapis.com/books/v1/volumes?q=isbn:";
var allresults = [];
for (var i = 0; i < bookList.length; i++) {
$.ajax({
url: thelink + bookList[i],
dataType: 'json',
type: 'get',
cache: true,
success: function (data) {
allresults.push(data);
// check if it's the last result, if so check all the values inside allresult
}
});
};
Related
This question already has answers here:
Large numbers erroneously rounded in JavaScript
(6 answers)
Closed 5 years ago.
I've got a script which gets a bunch of information from an api and then lists it on my site. I then have a function, newLink(z) which is supposed to get the information from the new elements created and do stuff with it, to simplify it I'm just trying to console.log whatever it says below. Any number that I put into the brackets of the function, in this case 76561198008132325, has the last digit replaced with a 0 for whatever reason, resulting in the console logging '76561198008132320'. I've been scratching my head on this for a good half hour now and I literally can not figure out what is causing this.
var searchRequest = "https://api.roleplay.co.uk/v1/search/player?name=ant";
var searchData = "";
function success(data) {
for (i = 0; i < data['length']; i++) {
document.getElementById("searchResults").innerHTML += "<div class='result' onclick='newLink(76561198008132325)'>new link</div>";
}
}
function newLink(z) {
console.log(z);
}
$.ajax({
dataType: 'json',
url: searchRequest,
data: searchData,
success: success
});
<div class="results" id="searchResults">
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
This is because you are passing the argument to the function as Number. Pass the argument value as string.
var searchRequest = "https://api.roleplay.co.uk/v1/search/player?name=ant";
var searchData = "";
function success(data) {
for (i = 0; i < data['length']; i++) {
document.getElementById("searchResults").innerHTML += "<div class='result' onclick='newLink(\"76561198008132325\")'>new link</div>";
}
}
function newLink(z) {
console.log(z);
}
$.ajax({
dataType: 'json',
url: searchRequest,
data: searchData,
success: success
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="results" id="searchResults">
</div>
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 5 years ago.
I'm trying to print through innerHTML some data got with the ajax call, but the global array elements it is not accesible in the done() promise.It is indeed undefined.
Why does that happen?
<html>
<head></head>
<body>
<script src ="jquery.min.js"></script>
<script>
$(document).ready(function(){
var elements = document.getElementsByClassName("wind");
for(i=0;i<elements.length;i=i+1){
$.ajax({
type:"GET",
url:"http://api.openweathermap.org/data/2.5/weather?q="+elements[i].innerHTML+"&appid=7876b25bdca1397553df39ef3ea05fd1",
dataType: "json"
}).done(function(data){
elements[i].innerHTML = data.wind.speed; //elements[i] is undefined
});
//elements[i].innerHTML here elements[i] is OK but I don't have access to "data"
}
});
</script>
<div class="wind">Venice,it</div>
<div class="wind">Rome,it</div>
</body>
Try using the success setting rather than done. This will activate when the request is successful and it returns the data.
$.ajax({
type:"GET",
url:"http://api.openweathermap.org/data/2.5/weather?q="+elements[i].innerHTML+"&appid=7876b25bdca1397553df39ef3ea05fd1",
dataType: "json",
success: (function(data){
elements[i].innerHTML = data.wind.speed;
}),
});
I have two different sets of a and p elements in my html page which are made as display:none by default.
At the end of the of the page I'm calling a function by sending their ID's and some values to enable any one of them based on some conditions
1st set
<a style="display:none;" id="ClickMe1">Click Me</a>
<p class="button" id="Sorry1" style="display:none;">Sorry!</p>
2nd set
<a style="display:none;" id="ClickMe2">Click Me</a>
<p class="button" id="Sorry2" style="display:none;">Sorry!</p>
Function call
<script>
window.onload = function () {
Initialize("ClickMe1", "Sorry1", "23,35");
Initialize("ClickMe2", "Sorry2", "76,121");
};
</script>
Initialize function consists of a ID, p ID and set of values(it can contain n values) to check which element to enable
Javascript Function
function Initialize(ClickMeID, SorryID,Values) {
var valList = Values.split(',');
for (i = 0; i < valList.length; i++) {
var paramts = "{'val':'" + valList[i] + "'}";
jQuery.ajax({
type: "POST",
url: "/services/MyService.asmx/GetData",
data: paramts,
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false,
success: function (response) {
Status = response.d.toString();
},
error: function (response) {
}
});
if (Status == "0") {
$('#' + SorryID).show();
return;
}
}
$('#' + (ClickMeID).show();
}
In my function I'm splitting the comma seperated Values and looping through each value and making an ajax call to my service with async:false.
The response of success call is either 1 or 0. If any of Values is 0 of a function call I want to display p element else a element of the sent ID's.
This function is working fine but when the function call is raised this is making the browser freeze until the execution of the function.
If I make async: true I'm not able to find out which set of buttons to enable and disable
How can I make prevent the browser from freezing.
You should set
async: true
If it's not async, then it'll be blocking.
Also, if you're looping through many items, you should wrap each iteration in a setTimeout and make it async too.
Code samples
function click(e){
var button = e.target;
$.ajax({
type: "POST",
url: "http://localhost/accounts/save",
data : {
accountID: 123,
name:"hello world"
},
beforeSend: function(){
//disable the button.
}
}).always(function(){
//enable the button
})
}
here's an example of of setTimeout
setTimeout(function(){
//do something
}, 3000); //3seconds
I would highly recommend, that you read up on jquery.Deferred and event loops.
I'm not able to find out which set of buttons to enable and disable
Then that is your real issue. You solved your problem with other code to cause a new problem.
I highly suggest reading Decoupling Your HTML, CSS, and JavaScript.
Here is what I would do (since you tagged jquery might as well.. actually fully use it).
<style>
.is-hidden{ display: none; }
</style>
<div class="js-init-content" data-params="[{'val':23},{'val':35}]">
<a class="is-hidden js-clickme">Click Me</a>
<p class="button is-hidden js-sorry">Sorry!</p>
</div>
<div class="js-init-content" data-params="[{'val':76},{'val':121}]">
<a class="is-hidden js-clickme">Click Me</a>
<p class="button is-hidden js-sorry">Sorry!</p>
</div>
<script>
// when the document is ready...
$(document).ready(function(){
// loop through each init-content item
$(".js-init-content").each(function(){
var $this = $(this);
// get the data from the html element
// jquery will return an array containing objects
// because it's smart and cool like that
var params = $this.data('params');
var isAvailable = true;
// loop through each param
$.each(params, function(index, param){
// stop loop and ajax calls if any previous ajax call failed
if (!isAvailable) return false;
// make an ajax call, param will be the object from the array
$.ajax({
type: "POST",
url: "/services/MyService.asmx/GetData",
data: param,
contentType: "application/json; charset=utf-8",
// dataType: "json", -- jquery is smart it will figure it out
// async: false, -- Almost no reason to ever do this
).done(function(response){
isAvailable = response.d.toString() != "0";
}); // End Ajax-Done
}); // End js-init-content.each
var selector = isAvailable
? ".js-clickme"
: ".js-sorry";
$this.find(selector).removeClass("is-hidden");
}); // End doc-ready
</script>
I encapsulated the data in the html, instead of hardcoding it in the javascript. Fully used jQuery for loading and updating.
I'm using jQuery AJAX to get an array from a PHP file which is getting data from a MySQL database. I'm now trying to use that array outside my ajax call. Specifically I'm loading multiple videoIDs for YT.Player but I'm stumbling on getting my array to another function.
Here's my testing code:
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>
<script>
var data = new Array();
$(document).ready( function() {
$.ajax({
type: 'POST',
url: 'test.php',
data: 'id=testdata',
dataType: 'json',
cache: false,
success: function(result) {
data = result;
$('#div1').html(result[4]);
},
});
});
$("button").click(function(){
alert(data[4]);
});
</script>
</head>
<body>
<button id="button">Test</button>
<div id="div1"><h2>div1</h2></div>
</body>
</html>
The div changes a half second after the page loads as expected. The click function for testing doesn't work, and its not working in the real function I'm working on:
function onPlayerStateChange(event) {
if(event.data === 0) {
++i;
player.loadVideoById(data[i]);
}
}
This is my first project with jQuery and JS so I'm hoping I'm missing something simple
You should put
$("button").click(function(){
alert(data[4]);
});
inside
$(document).ready( function() {
});
Also, if you put var before variable then it becomes local variable.
So, you should either remove var before
data = new Array();
or just put as a additional parameter
function onPlayerStateChange(event, data) {
if(event.data === 0) {
++i;
player.loadVideoById(data[i]);
}
}
but then you also need to call it inside
$(document).ready(function() {} );
scope.
I am having trouble with jQuery with trying to modify a global variable from within the success callback:
<html>
<head>
<script type="text/javascript" src="javascript/jquery.min.js"></script>
<script type="text/javascript">
// Define items in the global scope
items = null;
// Get items from XML for a given category ID
function getItems(categoryID)
{
$.ajax({
type: 'GET',
url: 'items.xml',
dataType: 'xml',
success: function(xml){
items = $(xml).find('category[id="'+categoryID+'"]').children().first();
// This works (returns the name of the first item)
alert( items.attr('name') );
}
});
}
</script>
</head>
<body>
<script type="text/javascript">
$(function(){
getItems(1);
// This doesn't work (returns null)
alert( items.attr('name') );
});
</script>
</body>
</html>
What am I doing wrong?
This is because the callback hasnt finished by the time you are executing the alert.
the Get request is asynchronous so execution continues even if it has not finished. So when the alert() statement executes, the success callback has not yet executed, therefore items is still null.
You can either do a synchronous call, or include whatever you are trying to do inside the success callback.