Since my main language is C, I am used to pointers and I love them. Now I have some project which I need to finish in Javascript and I've got a problem which I don't know how to solve.
I want to store the value of a variable which I got from GET request. I have a script to send GET to PHP page, which then sends GET to my daemon written in C. When I get the string I wanted, I use length to measure the size of the string I got and in next GET request I want to send that number of bytes I got as the URL parameter.
window.onload = function() {
if (bytes === undefined) {
var bytes = 0;
}
var url = "/test/log.php?q=" + bytes;
function httpGet(url) {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", url, true);
xhttp.onload = function(e) {
if (xhttp.readyState === 4) {
if (xhttp.status === 200) {
console.log(xhttp.responseText);
var option = "";
obj = JSON.parse(xhttp.responseText);
for (var key in obj) {
option += obj[key];
}
document.getElementById("list").innerHTML = asdf;
bytes = option.length;
}
};
xhttp.onerror = function(e) {
console.error(xhttp.statusText);
}
};
xhttp.send();
}
var updateInterval = 2000;
function update() {
httpGet(url);
setTimeout(update, updateInterval);
}
update();
}
So, the focus is on the variable bytes. It should have the value 0 when the script is a first time called, and after every loop (it loops every 2 seconds, I didn't show the loop in the code) it should have the value of the previous length of received string.
You just need to make sure to add the bytes param onto your url in a way that changes with each call rather than just once at page load when it will always be 0.
window.onload = function() {
if (bytes === undefined) {
var bytes = 0;
}
var url = "/test/log.php?q=";
function httpGet(url) {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", url, true);
xhttp.onload = function(e) {
if (xhttp.readyState === 4) {
if (xhttp.status === 200) {
console.log(xhttp.responseText);
var option = "";
obj = JSON.parse(xhttp.responseText);
for (var key in obj) {
option += obj[key];
}
document.getElementById("list").innerHTML = asdf;
bytes = option.length;
}
};
xhttp.onerror = function(e) {
console.error(xhttp.statusText);
}
};
xhttp.send();
}
var updateInterval = 2000;
function update() {
httpGet(url + bytes);
setTimeout(update, updateInterval);
}
update();
}
Instead of a fixed value of url make it to a function and it will give you always the current Url with the modified version of bytes, if you modify it
You have only to change this parts
var url = ...
// to
function getUrl() {
return "/test/log.php?q=" + bytes;
}
...
// and
xhttp.open("GET", url, true);
// to
xhttp.open("GET", getUrl(), true);
I'd declare the variable in a context that doesn't empty its value when the function is called. So, you can declare your variable "bytes" before the function, and then looping through that function. In this case, the variable will hold the last value until you overwrite it.
That should work!
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
For this Javascript example, can somebody please explain on a very basic level why this is not working and how you properly create another (not nested) function that passes back a value to the function it was invoked from.
function function1() {
var x = 5;
function2(x);
console.log(y);
function3(y);
console.log(z);
}
function function2(y) {
var y = y + 5;
return y;
}
function function3(z) {
var z = z + 5;
return z;
}
Even when declaring them in the main function, it doesn't work:
function function1() {
var x = 5;
var y = function2(x);
console.log(y);
var z = function3(y);
console.log(z);
When using global variables, no difference. I also tried following other examples where you create 1 global object to write global variables to, but that also always fails with "undefined":
function function1() {
x = 5;
y = function2(x);
console.log(y);
z = function3(y);
console.log(z);
I guess I don't understand some very basic concept. Please shine some light. I can see subroutines running and doing what they need to do, but they never pass back the final value to the function that invoked the function.
Follow up question
I do a request to an API where I get a roomId. Next I try to call a function that does another API call to translate the roomId to a roomName. I want to pass the roomName back to the other function to use it there. I tried many things already, untill now not able to pass back the variable. As the previous example seem to work, it must have something to do with something else (array/object, string/nostring/...).
function GetMemberships() {
var xhttp = new XMLHttpRequest();
var url = "HIDDEN";
var method = "GET";
var shouldBeAsync = true;
xhttp.open(method, url, shouldBeAsync);
xhttp.setRequestHeader("Content-Type", "application/json");
xhttp.setRequestHeader("Authorization", "Bearer HIDDEN"); // API key of Bot
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
var jsonObj = JSON.parse(xhttp.responseText);
var roomId = jsonObj.items[0].roomId;
var roomId = JSON.stringify(roomId);
var roomId = roomId.replace(/"/g,'');
var roomName = GetNameOfRoom(roomId);
console.log(roomName) // UNDEFINED
}
};
xhttp.send();
}
function GetNameOfRoom(roomId) {
var xhttp = new XMLHttpRequest();
var url = "HIDDEN" + roomId;
var method = "GET";
var shouldBeAsync = true;
xhttp.open(method, url, shouldBeAsync);
xhttp.setRequestHeader("Content-Type", "application/json");
xhttp.setRequestHeader("Authorization", "Bearer HIDDEN");
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
var jsonObj = JSON.parse(xhttp.responseText);
var roomName = jsonObj.title;
console.log(roomName); // SHOWS CORRECT VALUE
return roomName;
}
};
xhttp.send();
}
So first you need a function invoke in which you declare your variables and assign them a certain value:
function invoke() {
var x, y = 0;
x = h(21);
y = g(42);
console.log(x);
console.log(y);
}
Then you create the functions in which you do your calculations:
function h(n) {
return n + 5;
}
function g(n) {
return n - 5;
}
Now you just need to call your function invoke in order to execute it:
invoke();
If you want to print out the calculations as well, add:
function invoke2(x,y) {
console.log(h(x));
console.log(g(y));
}
invoke2(21,42);
That should give you your result.
How to populate the select list with the values that I got with javascript?
I am sending a GET request to a .php site which gives me the respond in JSON format. Now I want to put those lines I got into the select list.
<select id = "list" name=log size=50 style=width:1028px>
<script type="text/javascript">
window.onload = function () {
var bytes=0;
var url = "/test/log.php?q='0'";
function httpGet(url)
{
var xhttp = new XMLHttpRequest();
var realurl = url + bytes;
xhttp.open("GET", url, true);
xhttp.onload = function (e) {
if (xhttp.readyState === 4) {
if (xhttp.status === 200) {
console.log(xhttp.responseText);
var response=JSON.parse(xhttp.responseText);
var log = response.key;
bytes = log.length;
}
};
xhttp.onerror = function (e) {
console.error(xhttp.statusText);
}
};
xhttp.send();
}
var updateInterval = 2000;
function update() {
httpGet(url);
setTimeout(update, updateInterval);
}
update();
}
</script>
</select>
The response I get from log.php is "{"key":"whole log file"}". Now I want to store that reponse into a list and populate it every 2 seconds.
Loop over the contents of the returned string after JSON.parse-ing it. Create option elements from it, and insert those into the select.
var html = "";
var obj = JSON.parse(xhttp.responseText);
for(var key in obj) {
html += "<option value=" + key + ">" +obj[key] + "</option>";
}
document.getElementById("list").innerHTML = html;
See JSBin
I'm generating a series of variables in a loop (using JS), and I'm assigning them an .id and a .name based on the current index. At each loop I'm sending a request to the server using jQuery.post()method, but the returning response is just an empty variable.
Here's the code:
JavaScript
for ( var index = 0; index < 5; index++ ) {
var myVar = document.createElement('p');
myVar.id = 'myVarID' + index;
myVar.name = 'myVarName' + index;
//Send request to server
$(document).ready(function(){
var data = {};
var i = 'ind';
var id = myVar.id;
var name = myVar.name;
data[id] = name;
data[i] = index;
$.post("script.php", data, function(data){
console.log("Server response:", data);
});
});
}
PHP
<?php
$index = $_POST['ind'];
$myVar = $_POST['myVarID'.$index];
echo $myVar;
?>
Response: Server response: ''
If I instead set a static index in JS code, getting rid of the loop, so for example:
var index = 0;
I get the expected result: Server response: myVarName0
Why is this happening? And how can I solve it?
Assuming the php file is in order. I use this:
function doThing(url) {
getRequest(
url,
doMe,
null
);
}
function doMe(responseText) {
var container = document.getElementById('hahaha');
container.innerHTML = responseText;
}
function getRequest(url, success, error) {
var req = false;
try{
// most browsers
req = new XMLHttpRequest();
} catch (e){
// IE
try{
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
// try an older version
try{
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
return false;
}
}
}
if (!req) return false;
if (typeof success != 'function') success = function () {};
if (typeof error!= 'function') error = function () {};
req.onreadystatechange = function(){
if(req .readyState == 4){
return req.status === 200 ?
success(req.responseText) : error(req.status)
;
}
}
var thing = "script.php?" + url;
req.open("GET", thing, true);
req.send(null);
return req;
}
then use it like this:
doThing("myVarID="+myVar.id+"&i="+index);
also, you will have to change your PHP to something like this:
<?php
$index = $_GET['ind'];
$myVar = $_GET['myVarID'.$index];
echo $myVar;
?>
Obviously this code needs to be edited to suit your own needs
the function doMe is what to do when the webpage responds, in that example I changed the element with the id hahaha to the response text.
This won't win you any prizes but it'll get the job done.
Solution
It is working fine removing:
$(document).ready()
Working code
for ( var index = 0; index < 5; index++ ) {
var myVar = document.createElement('p');
myVar.id = 'myVarID' + index;
myVar.name = 'myVarName' + index;
//Send request to server
var data = {};
var i = 'ind';
var id = myVar.id;
var name = myVar.name;
data[id] = name;
data[i] = index;
$.post("script.php", data, function(data){
console.log("Server response:", data);
});
}
I have implemented the code to check if the number of image files present in the server and then use it for gallery. The number of images are found correct but only the first image loads and does not change .
var gallerylength;
var galleryid = 1;
function UrlExists(url)
{
var http = new XMLHttpRequest();
http.open('HEAD', url, false);
http.send();
return http.status!=404;
}
function checksrc()
{
var index = 1;
var src = "images/splash/gallery/img";
for(index=1;UrlExists(src+index+".jpg");index++);
gallerylength = index;
}
function setimg()
{
var src = "images/splash/gallery/img";
{
$("#gallerywindow").attr("src",src+galleryid+".jpg");
if(galleryid<gallerylength-1)
galleryid++;
else
galleryid = 1;
}
}
$(document).ready(function(event)
{
checksrc();
setInterval(setimg(),1000);
});
In line: setInterval(setimg(),1000); you are calling the function, must be a reference to it: setInterval(setimg,1000);
$(document).ready(function(event)
{
checksrc();
setInterval(setimg, 1000);
//or
setInterval(function(){
setimg();
}, 1000);
});
I want to load an array of XML files, and store them in an array.
Code example:
var src = [ "a", "b", "c", "d" ];
var dest = {};
for (var i in src) {
var req = new XMLHttpRequest();
req.open("GET", src[i], true);
req.onreadystatechange = function(aEvt) {
if (req.readyState == 4) {
if (req.status == 200) {
dump(i + "\n");
dest[i] = req.responseXML;
}
}
}
req.send(null);
}
However, the dump result is always
3
3
3
3
It shows that the i referenced in callback is always the outer i, so the XML files cannot be stored correctly.
So, how to solve this issue? We have about 50 XML files to load and loading them one by one is not acceptable.
Thank you.
Don't use for..in to loop over arrays. Use a normal for loop.
You make the typical mistake of creating a function in a loop. JavaScript has no block scope, only function scope, so i will always refer to the last element of the array you looped over when the functions you created are executed. They all have a reference to the same i. You can solve this by using an immediately executing function that returns a function (thus, capturing the value of i).
If you do this, you also have to capture a reference to req, otherwise it will always refer to the last generated XMLHttpRequest (the same reason as for i).
So one solution would be:
var src = [ "a", "b", "c", "d" ];
var dest = {};
for (var i = src.length;i--;) {
var req = new XMLHttpRequest();
req.open("GET", xmlfile, true);
req.onreadystatechange = (function(i, req) {
return function(aEvt) {
if (req.readyState == 4) {
if (req.status == 200) {
dump(i + "\n");
dest[i] = req.responseXML;
}
}
};
}(i, req)); // capturing the current value/reference of i and req
req.send(null);
}
#Spiny Norman's solutions might be more readable ;)
You could do something like this:
var src = [ "a", "b", "c", "d" ];
var dest = {};
var loadXml = function(i) {
var req = new XMLHttpRequest();
req.open("GET", xmlfile, true);
req.onreadystatechange = function(aEvt) {
if (req.readyState == 4) {
if (req.status == 200) {
dump(i + "\n");
dest[i] = req.responseXML;
}
}
}
req.send(null);
};
for (var x = 0; x < src.length; x++) {
loadXml(x);
}
By the way, it seems you're always loading the same xmlfile, but I'm sure this is different in your actual code ;)