This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
Background: I am attempting to retrieve data, using AJAX, and assign it to a variable. I have tried to set the AJAX request to synchronous, but Firefox will not allow it.
Question: How can I make certain all the data is received?
function search(){
var data = [];
this.init = function(){
data = getData({"url":"/imglib/Inventory/cache/2335/VehInv.js"});
console.log(data); // Returns as 'undefined'. Possibly because of asynchronous call?
};
var d = new Date();
function getData(url){
var xhttp: new XMLHttpRequest();
var dataURL = url + '?v=' String(d.getTime());
xhttp.onreadystatechange = function(){
if(this.readyState = 4 && this.status == 200){
var r = this.responseText;
var s = r.indexOf('[') + 1;
var e = r.indexOf(']');
var jsonData = JSON.parse("[" + r.slice(s,e) + "]");
return jsonData;
}
};
xhttp.open("GET", dataURL, true);
xhttp.send();
}
};
you have to use a callback when working with asynchronous stuff..
function search(){
this.init = function(){
getData("http://www.petesrvvt.com/imglib/Inventory/cache/2335/VehInv.js", function(data){
console.log(data); // Returns as 'undefined'. Possibly because of asynchronous call?
});
};
var d = new Date();
function getData(url, callback){
var xhttp: new XMLHttpRequest();
var dataURL = url + '?v=' String(d.getTime());
xhttp.onreadystatechange = function(){
if(this.readyState = 4 && this.status == 200){
var r = this.responseText;
var s = r.indexOf('[') + 1;
var e = r.indexOf(']');
var jsonData = JSON.parse("[" + r.slice(s,e) + "]");
callback(jsonData);
}
};
xhttp.open("GET", dataURL, true);
xhttp.send();
}
};
Call the function that will deal with the data from the function invoked on "onreadystatechange". The reason it doesn't work is that the variable "data" isn't defined with the result of the async query when you are attempting to use it.
(function search() {
var data = [];
this.init = function() {
data = getData({
"url": "http://www.petesrvvt.com/imglib/Inventory/cache/2335/VehInv.js"
});
// This is definitely caused by the asynchronous XMLHttpRequest
//console.log(data); // This needs to be moved to the callback that is invoked when the request completes. See below
};
var d = new Date();
function getData(url) {
var xhttp: new XMLHttpRequest();
var dataURL = url + '?v='
String(d.getTime());
xhttp.onreadystatechange = function() {
if (this.readyState = 4 && this.status == 200) {
var r = this.responseText;
var s = r.indexOf('[') + 1;
var e = r.indexOf(']');
var jsonData = JSON.parse("[" + r.slice(s, e) + "]");
// This is how you be sure you get your data
console.log(jsonData);
}
};
xhttp.open("GET", dataURL, true);
xhttp.send();
}
})();
Related
I have a page that uses a function for getting some data, with a GET xhttp request, from a database (get_worktime_list()).
On the same page, I can add some data to the database with a form using a POST xhttp request and after a success (saved in the response) I will get the content included the new line from the database with the same function get_worktime_list().
The problem is that when getworktime is called after the POST request, get_worktime_list() makes another POST request instead of a GET. why???
function http_request(post_data, end_point, type)
{
console.log("HTTP");
var res = 0;
//var data = "data=0&username="+stored_token.username+"&token="+stored_token.token;
var data = "data=0&"+post_data;
console.log(data);
// Check if is valid token/username from database
const url = "http://192.168.1.188:5000/services/"+end_point;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
res = JSON.parse(xhttp.responseText);
}
};
if (type == "GET")
{
console.log(url+"?"+post_data);
xhttp.open("GET", url+"?"+post_data, false);
}
else
{
console.log("Data: "+data);
xhttp.open("POST", url, false);
}
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhttp.send(data);
xhttp.abort();
return res;
}
This add data to DB
function addworktime(username,token)
{
console.log("Aggiungo ore");
var date = document.getElementById("data").value;
var type = document.getElementById("turno").value;
var pay = document.getElementById("paga").value;
var emp = document.getElementById("dipendente").value;
var ore = document.getElementById("num_ore").value;
var data = "username="+username+"&token="+token+"&day="+date+"&turn_type="+type+"&pay="+pay+"&emp="+emp+"&ore="+ore;
var res = http_request(data,"admin/dipendenti/addtime.php","");
//console.log(res);
if (res.insert_ok == 1)
{
display_time_table(0,0,null);
} else {
console.log(res);
}
}
This function makes a GET request when a page load and a POST request when called by addworktime()
function display_time_table(from,to,cf)
{
let time_list_table = document.getElementById("list-container");
var time_list = get_worktime_list(saved_data.username,saved_data.token,from,to,cf);
let time_table = generate_time_list_table(time_list);
time_list_table.innerHTML = time_table;
}
function get_worktime_list(username,token,date_from,date_to,cf)
{
var data = "username="+username+"&token="+token;
if (cf != "" || cf != null)
{
data = data+ "&dipendente="+cf;
}
if (date_from != 0)
{
data = data +"&date_from="+date_from;
}
if (date_to != 0)
{
data = data + "&date_end="+date_to;
}
var time_list = http_request(data,"admin/dipendenti/getworktime.php", "GET");
return time_list;
}
The server can only accept GET requests for that API and obviously, I get a parse error parsing the JSON response.
Thanks for help
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
I'm trying to implement JavaScript tool for generating a random video from specific channel from youtube, I coded everything and it works fine in the console, however I cannot save the value in variable and to display the video later on my website. Is it possible to make the value of x (defined on the end of the pasted code) have the value of youtubeUrl
function getVideo() {
var channelId = "";
var apiKey = "";
var videosUrl = "https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId=" + channelId + "&maxResults=50&key=" + apiKey;
var ajax = new XMLHttpRequest();
ajax.open("GET", videosUrl, true);
ajax.send();
ajax.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
var json = JSON.parse(this.responseText);
var videos = json.items;
var randomNumber = Math.floor(Math.random() * (videos.length + 1));
var randomVideo = videos[randomNumber];
var videoId = randomVideo.id.videoId;
var videoUrl = "https://www.googleapis.com/youtube/v3/videos?id=" + videoId + "&part=snippet,contentDetails,statistics&key=" + apiKey;
var ajax = new XMLHttpRequest();
ajax.open("GET", videoUrl, true);
ajax.send();
ajax.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
var json = JSON.parse(this.responseText);
var singleVideo = json.items[0].id;
var youtubeUrl = "https://www.youtube.com/embed/" + singleVideo;
}
};
}
};
}
let x = getVideo(); // how to make it such that x has the value of youtubeUrl
Just wrap the content of your function inside a new Promise constructor and resolve it with the youtubeUrl:
function getVideo() {
return new Promise((resolve, reject) => {
var channelId = "";
var apiKey = "";
var videosUrl = "https://www.googleapis.com/youtube/v3/search?order=date&part=snippet&channelId=" + channelId + "&maxResults=50&key=" + apiKey;
var ajax = new XMLHttpRequest();
ajax.open("GET", videosUrl, true);
ajax.send();
ajax.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
var json = JSON.parse(this.responseText);
var videos = json.items;
var randomNumber = Math.floor(Math.random() * (videos.length + 1));
var randomVideo = videos[randomNumber];
var videoId = randomVideo.id.videoId;
var videoUrl = "https://www.googleapis.com/youtube/v3/videos?id=" + videoId + "&part=snippet,contentDetails,statistics&key=" + apiKey;
var ajax = new XMLHttpRequest();
ajax.open("GET", videoUrl, true);
ajax.send();
ajax.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
var json = JSON.parse(this.responseText);
var singleVideo = json.items[0].id;
var youtubeUrl = "https://www.youtube.com/embed/" + singleVideo;
resolve(youtubeUrl);
}
};
}
};
}
let x = await getVideo();
I would like to get an array with objects from json using XMLHttpRequest() and assign it to a variable.
If i log it in a console it shows the array.
function getData() {
let myJson = [];
var xhr = new XMLHttpRequest();
var url = 'https://www.reddit.com/r/funny.json';
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var jsonData = JSON.parse(xhr.responseText);
arr = jsonData.data.children;
for (let i = 0; i < arr.length; i++) {
let newObject = {};
newObject.title = arr[i].data.title;
newObject.upvotes = arr[i].data.ups;
newObject.score = arr[i].data.score;
newObject.num_comments = arr[i].data.num_comments;
newObject.created = arr[i].created_utc;
myJson.push(newObject);
}
}
};
xhr.open("GET", url, true);
xhr.send();
return myJson;
}
let data = getData();
console.log(data[0]);
But if I try to do anything with (console.log(data[0]);) it it returns undefined. What am I doing wrong? Thanks for any explanation! Cheers.
Just pass in the callback function instead of returning the value from an asynchronous XML HTTP request.
function getData(callback) {
var xhr = new XMLHttpRequest();
var url = 'https://www.reddit.com/r/funny.json';
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var jsonData = JSON.parse(xhr.responseText);
arr = jsonData.data.children;
let myJson = [];
for (let i = 0; i < arr.length; i++) {
let newObject = {};
newObject.title = arr[i].data.title;
newObject.upvotes = arr[i].data.ups;
newObject.score = arr[i].data.score;
newObject.num_comments = arr[i].data.num_comments;
newObject.created = arr[i].created_utc;
myJson.push(newObject);
}
// Invoke the callback now with your recieved JSON object
callback(myJson);
}
};
xhr.open("GET", url, true);
xhr.send();
}
getData(console.log);
Your return happens outside of the onreadystatechange. So you exit before you even have the data.
Pass in a callback function to call when you have the data, or have the asynchronous call return a JS Promise that resolves with the gotten data.
G'morning folks,
I just have a small problem to fix this issue:
I have a page which should GET some data from a url when opening and the display in the own content. But the GET url contains Parameters from my url.
So:
1. Get Parameters from my URL like www.mydomain.com?test=1&test1=bla
2. open GET with this parameters (1 and bla) and display result
Here my current version:
<body>
<h3>Visa Informationen</h3>
<p id="data"></p>
<script>
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
document.getElementById("data").innerHTML = myObj.response.visa.content;
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
</script>
<script>
function getURLParameter(name) {
var value = decodeURIComponent((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, ""])[1]);
return (value !== 'null') ? value : false;
}
var param = getURLParameter('test');
if (param) document.getElementById("testnr").innerHTML = param;
var param1 = getURLParameter('test1');
if (param1) document.getElementById("testnr1").innerHTML = param1;
var url = "https://api01.otherdomain.com?test=" + param + "&test1" + param1 + "&trv=0&vis=1"
</script>
</body>
Any hint where the problem is with this code?
Kind regards,
Chris
It seems like you having issue with script execution order.
I assume that testnr element coming from your XML ajax request.
You have two script block in your HTML and it will executed while page load.
When second script block is running your fist XMLHttpRequest not completed so it not able to find given HTML tag document.getElementById("testnr").innerHTML
To overcome this issue you need to execute script only after XMLHttpRequest request is completed.
In your case :
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
document.getElementById("data").innerHTML = myObj.response.visa.content;
// Execute new created function here
SetValues();
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
function getURLParameter(name) {
var value = decodeURIComponent((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, ""])[1]);
return (value !== 'null') ? value : false;
}
function SetValues()
{
var param = getURLParameter('test');
if (param) document.getElementById("testnr").innerHTML = param;
var param1 = getURLParameter('test1');
if (param1) document.getElementById("testnr1").innerHTML = param1;
var url = "https://api01.otherdomain.com?test=" + param + "&test1" + param1 + "&trv=0&vis=1"
}
</script>
Okay, i fixed the matter.
Here my result which works fine for me:
<script>
function getURLParameter(name) {
var value = decodeURIComponent((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search) || [, ""])[1]);
return (value !== 'null') ? value : false;
}
var param = getURLParameter('test');
var param1 = getURLParameter('test1');
var url = "https://api01.otherdomain.com?test=" + param + "&test1" + param1 + "&trv=0&vis=1"
</script>
<script>
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
document.getElementById("additionalContent").innerHTML = myObj.response.additionalContent;
document.getElementById("data").innerHTML = myObj.response.visa.content;
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
</script>
The issue I'm having is that I have a dynamic API call whose url changes everytime. So In order to get the proper URL I have to get the text on the page and parse it so it only the first part of the text, then concatenate that to the first part of the URL. When I try to pass the string to the async script it keeps coming up as undefined. How can I get the string into the async script?
Specifically get the string to this line of code:
xhr.open("GET", APIcall, true);
var ID = element(by.css(".sometext")).getText().then(function(getFirstPartOfText) {
//console.log(ID);
var thing = getFirstPartOfText
var thing2 = getFirstPartOfText.toString().split(" ");
var thing3 = thing2[0];
var API = "https://someAPIcall/read/";
APIcall = API + thing3;
return APIcall;
}).then(function(APIcall){
console.log(APIcall);
browser.executeAsyncScript(function(ApiCall) {
var callback = arguments[arguments.length - 1];
var xhr = new XMLHttpRequest();
xhr.open("GET", APIcall, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
callback(xhr.responseText);
}
};
xhr.send('');
}).then(function(str) {
console.log(str);
//var whatINeed = JSON.parse(str);
var ID = element(by.css(".sometext")).getText().then(function(getFirstPartOfText) {
// this is synchronous, so there's no need to chain it using .then()
var thing = getFirstPartOfText
var thing2 = getFirstPartOfText.toString().split(" ");
var thing3 = thing2[0];
var API = "https://someAPIcall/read/";
APIcall = API + thing3;
return APIcall;
});
call_something(ID); // ID should be set at this point.
function call_something (APIcall) {
console.log(APIcall);
browser.executeAsyncScript(function(ApiCall) {
var callback = arguments[arguments.length - 1];
var xhr = new XMLHttpRequest();
xhr.open("GET", APIcall, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
callback(xhr.responseText);
}
};
xhr.send('');
}).then(function(str) {
console.log(str);
}
}
There are multiple things going on here, first of all the callback in call_something is not required, you are still within webdriver's promise manager. So all you need to do is return the data for the next call chain. Also quote in xhr.send(''); inside the method are not required. All you need to do is call send() and JSON parse the response and return, the next then block should have the JSON result. If you are getting pure HTML, then make sure the URL is correct.
function call_something (APIcall) {
console.log(APIcall);
browser.executeAsyncScript(function(ApiCall) {
var xhr = new XMLHttpRequest();
xhr.open("GET", APIcall, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
return JSON.parse(xhr.responseText);
}
};
xhr.send();
}).then(function(str) {
console.log(str);
}
}
I was missing an extra parameter mentioned here
The first argument is a function which will be called
The second+ arguments will be passed as arguments to the function in the first argument.
var ID = element(by.css(".sometext")).getText().then(function(getFirstPartOfText) {
//console.log(ID);
var thing = getFirstPartOfText
var thing2 = getFirstPartOfText.toString().split(" ");
var thing3 = thing2[0];
var API = "https://someAPIcall/read/";
APIcall = API + thing3;
return APIcall;
}).then(function(APIcall){
console.log(APIcall);
browser.executeAsyncScript(function(ApiCall) {
var callback = arguments[arguments.length - 1];
var xhr = new XMLHttpRequest();
xhr.open("GET", APIcall, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
callback(xhr.responseText);
}
};
xhr.send('');
}, APIcall).then(function(str) {
console.log(str);
//var whatINeed = JSON.parse(str);