XMLHTTPRequest Repeating Entries on ChartJS - javascript

I'm using an XMLHTTPRequest to receive data from a PHP file. The PHP file will echo at a number, say 6, and the XMLHTTPRequest will grab it. This is an attempt to make the graph live.
The problem I'm having relates to ChartJS and these requests.
var Data;
function loadXMLDOC() {
var request = new XMLHttpRequest(); // create http request
request.onreadystatechange = function() {
if (request.readyState == 4 && request.status == 200) {
Data = this.responseText;
myChart.data.labels.push(" ");
myChart.data.datasets[0].data.push(Data);
// re-render the chart
myChart.update();
}
}
request.open('GET', "data.php", true);
request.send(); // send the request
}
setInterval(function(){
loadXMLDOC();
}, 1000)
window.onload = loadXMLDoc;
As I'm grabbing these numbers from a database, I only need the number once. However, it will repeat the number multiple times, not once.
Numbers Repeating on ChartJS
I was wondering how I would only get the number once and have it not repeat multiple times till the next number comes in?

As Manuel suggested you can check if the latest number added is the same number as you want to add. If this is the case dont add it. Side effect from this is, if the next number is actually the same number as the last one it also wont be added. To achieve this you can change your function to this:
if (request.readyState == 4 && request.status == 200) {
Data = this.responseText;
const chartData = myChart.data.datasets[0].data;
if (chartData[chartData.length - 1] === Data) {
return;
}
myChart.data.labels.push(" ");
myChart.data.datasets[0].data.push(Data);
// re-render the chart
myChart.update();
}
Another option is to let PhP not send the number if it already has been sent.

Related

I can't get a response from the server

I followed some guides on how to send json objects to the server(written using node.js) and it doesn't work, I have no idea what is wrong. I know that my server works fine since I tested it on postman so it's my js code that's the problem, all the tutorials I see follow a similar XMLHttpRequest format.
this is my code
var ing = new Ingredient(name, date, qty, rp);
var url = "http://localhost:8081/addIngredient";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
//Send the proper header information along with the request
// application/json is sending json format data
xhr.setRequestHeader("Content-type", "application/json");
// Create a state change callback
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// Print received data from server
result.innerHTML = this.responseText;
}
};
// Converting JSON data to string
var data = JSON.stringify(ing);
document.write(data);
// Sending data with the request
xhr.send(data);
I used document.write to check where the code stops working but everything passes (since the document.write prints something), I suspect that there is something wrong/missing from xhr.send(data) but I can't tell what. Finally, nothing gets printed from the callback.
It's better to use onload instead of onreadystatechange
xhr.onload = function() {
if (xhr.status == 200) {
console.log(`Response length = ${xhr.response.length}`);
// store xhr.response here somewhere
}
};

Unable to get the same results with 2 pieces of somewhat similar XMLHttpRequest

Hope you are able to help or just help me understand why I have 2 almost similar codeblocks where one does not do what I expect.
I am trying to make some API calls where I populate a variable with the data that is pulled from the API call. In the first there is no problem at all, but the second I can't populate the variable.
I have tried googling the problem and it seems to be because of the asynchronous nature of XmlHttprequests. But again, I do not get why one solutions works and another don't.
The solution that work:
// Get JSON and convert it to an object
var obj;
const Http = new XMLHttpRequest();
const url = "https://type.fit/api/quotes";
Http.open("GET", url);
Http.send();
Http.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
obj = JSON.parse(Http.responseText);
}
};
In this solution I am able to get the data and populate the variable obj and use it globally.
link to the solution: https://codepen.io/Kfriis/pen/QWjGZmx
The solution that don't work:
//function that takes a currency in capital letters and returns
var rates;
var currency = 'gbp';
const currencyString = currency.toUpperCase();
const API = "api.frankfurter.app"
const URL = `https://${API}/latest?amount=1&from=${currencyString}&to=DKK`
const http = new XMLHttpRequest();
http.open("GET", URL);
http.send();
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
rates = JSON.parse(http.responseText);
}
};
console.log(rates)
This do, for some reason, not work. I do not get why the rates variable do not get populated since the request is basically the same for the first code snippet.
I have come down to an idea of it being because the data sent from the 2 API endpoints may be different in some way. Because if it was only because of the asynchronous requests, both code snippets should return undefined.
Link https://codepen.io/Kfriis/pen/VwvpKmd
I do hope someone is able to shine some light on this.
I must be doing something wrong in the second snippet, because I can console.log() from inside the onreadystatechange but not outside it. Which led me to believe for a long time that it was a scoping issue.
Your code does work. However, you're logging console.log(rates) outside the http.onreadystatechange-function which means you're logging the rates before you get the response. If you change the code block
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
rates = JSON.parse(http.responseText);
}
};
console.log(rates)
to
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
rates = JSON.parse(http.responseText);
console.log(rates)
}
};
it should work.
Here's a working example code if you wanna add the code to a function.
// Function that takes a currency in capital letters and returns
function getCurrencyRates(currency, cb) {
const currencyString = currency.toUpperCase();
const API = "api.frankfurter.app"
const URL = `https://${API}/latest?amount=1&from=${currencyString}&to=DKK`
const http = new XMLHttpRequest();
http.open("GET", URL);
http.send();
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
cb(JSON.parse(http.responseText));
}
};
}
// Call the function and pass "gbp" as currency.
// Rates will be logged in response.
getCurrencyRates('gbp', function(response) {
console.log(response);
});

PHP request timing

I'm writing a program to generate a random number in php, return it to a webpage and plot it on a graph. I've been debugging it a little and have noticed that when I call the request function, the webpage goes through the rest of the caller function before using returning the data from PHP. I need to get the data from the request and return it to the caller, then move on forward with the data I received from the request.
Here's the part of the caller function that keeps track in the console:
function plotData(dataSet) {
var x = xScale+20; // 20 = margin length
var y = 260; //origin of graph
getRequest();
console.log("x = "+x);
context.beginPath();
x=x+xScale; //Move along the xAxis
console.log("dataSet = "+dataSet[0]+", "+dataSet[1]);
...
}
And here's my PHP request:
function getRequest()
{
var request;
if (window.XMLHttpRequest)
{ // Mozilla, Safari, IE7+ ...
request = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{ // IE 6 and older
request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.onreadystatechange = function()
{
console.log('onReady');
if (request.readyState === XMLHttpRequest.DONE)
{
if (request.status === 200)
{
random = request.responseText;
random = parseInt(random);
random = random/100;
random = random.toFixed(2);
console.log("random = " +random);
data[1] = random;
console.log("data = "+data[0]+", "+data[1]);
}
else
{
alert ('There was a problem with the request');
}
}
}
request.open("GET", "external.php", true);
request.send();
}
And finally the console log:
onReady
x = 31.21951219512195
dataSet = 10, 10
onReady (x3)
random = 10.25
data = 10, 10.25
As you can see, the program is calling the all the console.log functions from plotData() before calling the functions from getRequest().
This is problematic because I need to get the information from getRequest() before I can continue with plotData().
One possible solution I just thought of is to make a 3rd function that executes after plotData() which does what I need it to do, but I feel like I should be able to handle it with the functions that I have.
Can someone explain why it goes through the caller function before the request function? And how can I fix it to wait for the request function to finish before moving forward with the caller?

Using a while loop to get rows using PhpExcel

I am looking to create javascript arrays with rows taken from an xlsx spread sheet using PHPExcel.
Here is my code
$document.ready({
var rows = new Array();
var vals = new Array();
var i = 0;
while(){
rows[i] = getRow(i);
vals[i] = getVal(i);
i++;
}
});
function getRow(i){
if(window.XMLHttpRequest){
xmlhttp= new XMLHttpRequest();
}else{
xmlhttp= new ActiveXObject('Microsoft.XMLHTTP');
}
xmlhttp.onreadystatechange = function (){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
return xmlhttp.responseText;
}
}
xmlhttp.open('GET', 'data.inc.php?x='+i, true);
xmlhttp.send();
}
function getVal(i){
if(window.XMLHttpRequest){
xmlhttp= new XMLHttpRequest();
}else{
xmlhttp= new ActiveXObject('Microsoft.XMLHTTP');
}
xmlhttp.onreadystatechange = function (){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
return xmlhttp.responseText;
}
}
xmlhttp.open('GET', 'include.inc.php?x='+i, true);
xmlhttp.send();
}
I am not sure what to check for in the parameter of the while loop (Im assuming we do not know how many rows are in the spreadsheet)
Is that my only issue or this the wrong way to go about it?
Also the function getRow return the entire row and getVal returns one column that will be important elsewhere on the page.
There are different approaches you can use:
1) Synchronise your requests:
function getRow(i, rows){
...
xmlhttp.onreadystatechange = function (){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
if xmlhttp.responseText != '' {
rows[i] = xmlhttp.responseText;
getRow(i+1, rows)
} else {
// call function that works with rows.
}
}
}
...
}
This function is only called with getRows(0, rows) (no loop!).
This is definitely the slowest approach because every request is started as soon as the previous request has finished.
2) Send number of rows first:
You could send the number of rows with the first or with each request, so javascript knows how many rows there are. Then you can loop over the rows and create asynchronous calls as you do now.
3) Send all rows at once:
I don't know your use case, but it looks like a waste of time to call every row separately. Why not make one call and return all of the data at once with linebreaks as delimiters (or something else suiting your data). If your data is really huge you could still break down the data into large chunks and combine this with option 1 or option 2.
4) Send data at page load:
Not sure if this is an option it looks like it is since you execute your function on document.ready. You could consider writing your data into a special hidden div and read the data from there (with javascript) into your variables. That way you avoid all the ajax calls. This is probably the fastest if you want to load all data anyway.
Note: you might consider using jQuery which makes working with ajax a lot easier. Check jQuery get for example.

Simultaneous ajax calls

I'm trying to make 2 (or more) ajax calls simultaneously. I don't want to use jQuery, only pure JavaScript.
Most of the time, it works. data1 will output data from sample.com/ajax1 and data2 will output data from sample.com/ajax2, but sometimes (1 from 10) the second AJAX call will display result from the first one.
Why is this happening? Both AJAX requests are requesting data from the same domain, but from different URLs. Is there any way how to prevent this behavior?
Here is the script:
// First AJAX
var xmlhttp1;
// Second AJAX
var xmlhttp2;
if (window.XMLHttpRequest) {
xmlhttp1 = new XMLHttpRequest();
} else {
xmlhttp1 = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp1.onreadystatechange = function() {
if (xmlhttp1.readyState == 4 && xmlhttp1.status == 200) {
data = JSON.parse(xmlhttp1.responseText);
console.log('data1: ' + data);
}
}
xmlhttp1.open("GET", "http://sample.com/ajax1", true);
xmlhttp1.send();
if (window.XMLHttpRequest) {
xmlhttp2 = new XMLHttpRequest();
} else {
xmlhttp2 = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp2.onreadystatechange = function() {
if (xmlhttp2.readyState == 4 && xmlhttp2.status == 200) {
data = JSON.parse(xmlhttp2.responseText);
console.log('data2: ' + data);
}
}
xmlhttp2.open("GET", "http://sample.com/ajax2", true);
xmlhttp2.send();
First of all, I recomment wrapping your xmlHttpRequest generation/handling in a function, so you don't duplicate code that much.
The problem you have there is that the data variable is global, so both ajax callbacks are using the same variable. You can fix it using the var keyword in both calls.
xmlhttp2.onreadystatechange = function() {
if (xmlhttp2.readyState == 4 && xmlhttp2.status == 200) {
var data = JSON.parse(xmlhttp2.responseText);
console.log('data2: ' + data);
}
}
Because you're not properly encapsulating data. The way you have it written, data is a global object, so it's available to be modified by either ajax call. Since ajax calls are asynchronous, this will lead to unpredictable values for data.
The problem is probably because you forgot to define data inside your function
anyway with this function you can create multiple requests and have more control over them..
var req={};
function ajax(a){
var i=Date.now()+((Math.random()*1000)>>0);
req[i]=new XMLHttpRequest;
req[i].i=i;
req[i].open('GET',a);
req[i].onload=LOG;
req[i].send();
}
function LOG(){
console.log(this.i,this.response);
delete req[this.i];//clear
}
window.onload=function(){
ajax('1.html');
ajax('2.html');
ajax('3.html');
}
uses xhr2... you need to modify the code to make it work with older browsers.

Categories

Resources