This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 9 months ago.
I am not used to asynchronous method so I would like to have your help. I have this ajax method that gets the data of my mysql tables. I need to retrieve this data to use it in my code.
Here is my code :
function ajaxRequest(type,url,callback,data=""){
let request = new XMLHttpRequest();
request.open(type, url);
request.onload = function () {
switch (request.status){
case 200:
case 201: //console.log(request.responseText);
callback(request.responseText);
break;
default: console.log(request.status);
}
};
request.send(data);
}
function setAvailableQuestions(){
ajaxRequest("GET","../controller.php?func=get_availableQuestion", (questions) => {
var allQuestions = JSON.parse(questions);
return allQuestions;
});
}
function getNewQuestion(){
var availableQuestions = setAvailableQuestions();
console.log(availableQuestions); //undefined
}
I read that you could solve it in two different ways, first one is to put ajax request asynchronous to false :
function setAvailableQuestions(){
var ajax = new XMLHttpRequest();
var asynchronous = false;
ajax.open("GET","../controller.php?func=get_availableQuestion", asynchronous);
ajax.send();
ajax.onreadystatechange = function(){
var allQuestions = JSON.parse(this.response);
return allQuestions;
}
}
function getNewQuestion(){
var availableQuestions = setAvailableQuestions();
console.log(availableQuestions); //undefined
}
But it still displays undefined
And the other method is to use .then or await for asynchronous methods but I don't know how to apply it to my first code.
Does anyone has an idea to help me ?
Try setting the "return" on setAvailableQuestions().
function setAvailableQuestions(){
var ajax = new XMLHttpRequest();
var asynchronous = false;
ajax.open("GET","../controller.php?func=get_availableQuestion", asynchronous);
ajax.send();
ajax.onreadystatechange = function(){
var allQuestions = JSON.parse(this.response);
return allQuestions;
}
return ajax.onreadystatechange;
}
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 10 months ago.
I'm trying to access the NHL API for a personal project. I was getting CORS request errors and found the below solution to access all the different sites (some worked prior, and some didn't).
I'm passing through a link and based one the outputs it seems to be accessing the data on the page and displaying it in both JSON and string format. The only problem is I can't return any of that data out of the function as an object or otherwise.
Last 2 logs show undefined, and the 2 within the function output the data I want. Am I missing something obvious or is there a deeper issue with the website access?
Thanks.
function getJSON(url){
let request = new XMLHttpRequest();
request.open('GET', url);
request.onload = function () {
// Begin accessing JSON data here
let data = JSON.parse(this.response);
if (request.status >= 200 && request.status < 400) {
//Start writing function here
console.log(data);
console.log(JSON.stringify(data));
let data2 = JSON.stringify(data)
return data2
} else {
console.log('error');
}
}
request.send();
}
let data1 = getJSON("https://statsapi.web.nhl.com/api/v1/people/8476459/stats?stats=statsSingleSeason&season=20212022")
console.log(data1);
console.log(JSON.stringify(data1));
You are doing asynchronous call, which means you return the value before the response even come back, that's why data1 is undefined
You can see this post for more information.
For your case, you can wrap the request with Promise
async function getJSON(url) {
return new Promise(function (resolve, reject) {
let request = new XMLHttpRequest();
request.open('GET', url);
request.onload = function () {
// Begin accessing JSON data here
let data = JSON.parse(this.response);
if (request.status >= 200 && request.status < 400) {
//Start writing function here
let data2 = JSON.stringify(data)
return resolve(data);
} else {
return reject('error')
}
}
request.send();
}
)
}
async function main() {
let data1 = await getJSON("https://statsapi.web.nhl.com/api/v1/people/8476459/stats?stats=statsSingleSeason&season=20212022")
console.log(data1);
console.log(JSON.stringify(data1));
}
main();
A better way is to use Fetch API
async function getJSON(url) {
const data1 = await fetch(url).
then(response => response.json());
return data1;
}
async function main() {
const result = await getJSON('https://statsapi.web.nhl.com/api/v1/people/8476459/stats?stats=statsSingleSeason&season=20212022');
console.log(result);
}
main();
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
What is the best method to save a XMLHttpRequest to a variable to use in a if statement. I'm trying to get the image size and depending on the size do something.
** *Please note that I'm using a random image from the internet for this question. I'm currently testing using a local server * **
This is what I have tried so far:
function get_image_size(imgurl) {
var xhr = new XMLHttpRequest();
let x
xhr.open('HEAD', imgurl, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
x = xhr.getResponseHeader('Content-Length');
console.log(xhr.getResponseHeader('Content-Length')) // This works! returns bytes
} else {
console.log('ERROR');
}
}
};
xhr.send(null);
console.log(x) // This doesn't work
return x // This doesnt return anything
}
let image_size = get_image_size("https://images.ctfassets.net/hrltx12pl8hq/7yQR5uJhwEkRfjwMFJ7bUK/dc52a0913e8ff8b5c276177890eb0129/offset_comp_772626-opt.jpg?fit=fill&w=800&h=300")
// image_size returns "undifined"
I've also tried:
function get_filesize(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open("HEAD", url, true);
xhr.onreadystatechange = function() {
if (this.readyState == this.DONE) {
callback(parseInt(xhr.getResponseHeader("Content-Length")));
}
};
xhr.send();
}
get_filesize("https://images.ctfassets.net/hrltx12pl8hq/7yQR5uJhwEkRfjwMFJ7bUK/dc52a0913e8ff8b5c276177890eb0129/offset_comp_772626-opt.jpg?fit=fill&w=800&h=300", function(size){image_size = size})
But still no luck.
You're making an asynchronous request, therefore, you can't have the value you need immediately assigned to x for use, your code needs a way to await the request before you can use or return x;
One approach is to wrap your get_image_size function in a Promise like this
function get_image_size(imgurl) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open('HEAD', imgurl, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
resolve(xhr.getResponseHeader('Content-Length'))
} else {
console.log('ERROR');
}
}
};
xhr.send(null);
})
}
and use it like this
const IMAGE_URL = "https://images.ctfassets.net/hrltx12pl8hq/7yQR5uJhwEkRfjwMFJ7bUK/dc52a0913e8ff8b5c276177890eb0129/offset_comp_772626-opt.jpg?fit=fill&w=800&h=300";
get_image_size(IMAGE_URL).then((size) => {
console.log(size)
// YOU CAN ONLY USE SIZE HERE.
// NOT OUTSIDE OR REASSIGNED
// COS IT MAY NOT BE AVAILABLE AS THIS IS AN ASYNCHRONOUS OPERATION
})
You can only use the value of size inside the callback of the chained .then() method.
It will NOT work if you reassign or try to access it from outside, as it may not be available at the time your code executes.
Another approach is to use the callback function, which I see you have tried, but the problem is that you were reassigning it like this image_size = size.
You can only use it within that callback function.
So technically you need to wrap all the code that needs the image-size inside that callback.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
How do I promisify native XHR?
(6 answers)
Closed 3 years ago.
i have some problem with ordering my functions.
i have 2 function. Two of them to http requests.
what a scenario?
on first request i get some response and in this response i'm getting some string and set it to some variable.
on second request i'm adding this string to my request url.
but my second request working before then in first request response when i set my variable.
because of that i'm getting undefined value of my variable.
I understand this is sync, async problem but how i can resolve this issue ?
it's my variable which i will add end of the second request url.
var urlString = '';
this is my first request:
var requestone = new XMLHttpRequest();
requestone.onload = function () {
if (requestone.status >= 200 && requestone.status < 300) {
var data = requestone.response;
data = JSON.parse(data);
urlString = data.Key
} else {
console.log('fail')
}
};
requestone.open('GET', 'apiurl');
requestone.send();
this is my second request:
var requesttwo = new XMLHttpRequest();
requesttwo.onload = function () {
if (requesttwo.status >= 200 && requesttwo.status < 300) {
var data = requesttwo.response;
} else {
console.log('fail')
}
};
requesttwo.open('GET', 'apiurl' + urlString);
requesttwo.send();
You can do this in 2 ways, using promise, or integrate the second request inside the request1:
var requestone = new XMLHttpRequest();
requestone.onload = function () {
if (requestone.status >= 200 && requestone.status < 300) {
var data = requestone.response;
data = JSON.parse(data);
requesttwo.open('GET', 'apiurl' + data.Key);
requesttwo.send();
} else {
console.log('fail')
}
};
requestone.open('GET', 'apiurl');
requestone.send();
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I'm still quite a noob at Javascript and one thing that I'm struggling to wrap my head round is forcing synchronicity into a primarily asynchronous programming language.
I have a function that loads a decent size JSON file and another function that utilises the return of this function.
I have read a lot of other threads about similar issues and keep seeing very different solutions, I was just curious what the best way to handle this would be.
Constructor calling the two functions -
class Guild extends MapObject {
constructor(x,y,floor,type,name) {
super(x,y,floor);
this.levels = [];
this.type = type;
this.name = name;
this.guildSelector();
this.addLevels(this.name);
this.setTip();
}
guildSelector function that loads the JSON and returns it as this.guildData
guildSelector(){
var oReq = new XMLHttpRequest();
this.guildData = null;
oReq.onload = reqListener;
oReq.open("get", "/json/guilds.json", true);
oReq.send();
function reqListener() {
this.guildData = JSON.parse(this.responseText);
console.log(this.guildData);
return this.guildData;
}
}
addLevels function that currently runs before this.guildData is populated with the JSON causing it to crash as it can't find .guilds of null.
addLevels(name) {
if(name == "default"){
this.name = "lowerSchoolOfEndurance";
}
console.log(this.guildData);
this.guildData.guilds.forEach(function(guild) {
console.log(guild.name);
if(guild.name == name){
for(var i = 1; i <= guild.levels.length; i++){
var guildStats = guild.levels[i-1];
for (var k in guildStats) {
console.log("Level "+i+" of the guild "+name+" increases "+k+" stat by "+guildStats[k]);
this.levels.push(guild.levels[i-1]);
}
}
}
});
return this.levels;
}
So the TL:DR would essentially be, what is the best way to not trigger my class that requires the JSON to be loaded until the JSON is loaded.
Kind Regards,
Earl Lemongrab
You should use Promises:
guildSelector(){
return new Promise((resolve, reject) => {
var oReq = new XMLHttpRequest();
this.guildData = null;
oReq.onload = reqListener;
oReq.open("get", "/json/guilds.json", true);
oReq.send();
function reqListener() {
this.guildData = JSON.parse(this.responseText);
resolve(this.guildData);
}
})
}
Then change your constructor to utilize the Promise:
this.guildSelector().then((guildData) => {
this.guildData = guildData;
this.addLevels(this.name);
});
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I'd like to create unique function for ajax post request.
This is actual source code:
function doAjax(url, postData) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
return xhttp.responseText;
}
};
xhttp.open("POST", url, true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(postData);
}
console.log( doAjax('shipment.php', 'fname=test1&lname=test2') );
But it's not working, the console shows "undefined".
But, if I change return on alert() - everything is OK.
So, why return now working ?
Your function doAjax does not actually return something. When you do xhttp.onreadystatechange = function() {...}; you just set a callback for an event that means this function isn't triggered immediately. No matter what you want to do, you will have to do (or trigger) it inside your callback.