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.
Related
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.
I have a function that loads a JSON file and gives it to a variable called articles. When i log articles inside of the function, it shows my json file, but when i log it outside of my function it doesn't show anything at all
I have tried to use let and var before articles inside of the function but that doesn't seem to work
var articles = ""
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if(xmlhttp.status == 200 && xmlhttp.readyState == 4){
articles = xmlhttp.responseText;
console.log(articles);
}
};
console.log(articles);
console.log(xmlhttp);
xmlhttp.open("GET","articles.json",true);
xmlhttp.send();
I want to be able to call my json file outside of my function by using articles, so that i don't have ot type xml.responseText each time.
In short, JavaScript does not synchronously wait for I/O operations to finish (network call in this case).
What this means is that when you log articles "outside of the function", the articles variable has not yet been set (the http request has not been completed).
Why are you hoping to have access to articles globally?
You could optionally pass your articles into a processing method after the http request has responded like so:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function(){
if(xmlhttp.status == 200 && xmlhttp.readyState == 4){
var articles = xmlhttp.responseText;
processArticles(articles)
}
};
xmlhttp.open("GET","articles.json",true);
xmlhttp.send();
function processArticles(articles) {
// Do something with articles here
}
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.
I have a request system where two unrelated functions are making requests to my server. But the problem is the response is not correct let me explain what is happening step by step:
A background function makes a request to the server
Server processes task 1
A second unrelated background function makes a request to the server
Client recieves response of task 1
The second function recieves that response that was for the first function.
The first function never gets a response.
Now i don't know how to solve it, but i know i need to distinguish them separately so theres no conflictions here.
This is my current code that handles the request stuff:
function call_back(result,func){
if(typeof(func) != 'undefined' || func != false){
func(result);
} else {
return false;
}
}
function caller(url,cfunc){
if (window.XMLHttpRequest)
{
xmlhttp=new XMLHttpRequest();
}
else
{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=cfunc;
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
function call_file(url,func){ //handles html files (not json_encoded)
caller(url,function(){
if ( xmlhttp.readyState== 4 && xmlhttp.status== 200 ){
call_back(xmlhttp.responseText,func);
}
});
}
function call_data(url,func,JsonBool){ //handles json_encoded data
caller(url,function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
call_back(JSON.parse(xmlhttp.responseText),func);
}
});
}
What can i do to my functions, for preventing this behaviour?
Here is an example of how you could structure your code - I have used this, it works, but it could be refined.
function Ajax(url, callback,args){
var xhttp = init();
xhttp.onreadystatechange = process;
function init() {
if(window.XMLHttpRequest)
return new XMLHttpRequest();
else if (window.ActiveXObject)
return new ActiveXObject("Microsoft.XMLHTTP");
}
function process() {
if (xhttp.readyState==4 && xhttp.status==200) {
if (callback) callback(xhttp.responseText,args);
else return xhttp.responseText;
}
}
this.Get=function(){
xhttp.open("GET", url, true);
xhttp.send(null);
}
}
To use it:
var url = '/someurl';
var ajax = new Ajax(url,yourCallback,parameters);
ajax.Get();
I believe DRobinson was talking about something like this but more robust. This should be a good example to get you started though.
It looks to me as though you're using a global/window variable for xmlhttp. If this is the case, certain parts of the second call will overwrite the first. Consider using an Object Oriented approach, or otherwise instantiating these as vars in different scopes.
I am reading a comma separated text file from the server, i get the valuse but when i chage the comma seprated variables in the file, it doesn't load the correct result int the browser
while browser persist the first time variable list only, whlile it works correct in IE, in firefox i am facig this proble.
How to sort it out
var arrUserTags = new Array();
var txt;
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "/TinyEditor/TextFile.txt", true);
xmlhttp.send();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
txt = xmlhttp.responseText;
arrUserTags = txt.split(",");
alert(arrUserTags.length);
parse();
}
}
// Add some values to the list box
function parse() {
for (i = 0; i < arrUserTags.length; i++) {
mlb.add(arrUserTags[i], arrUserTags[i]);
alert('hi');
}
}
You server is presumably sending caching instructions that tell browsers the URI for the text file won't change for a while.
Either configure the server to send no cache headers, or change the URI (e.g. by adding a rand() query string to it).