After leaving .get array loses data - javascript

I know there is something I am missing about Ajax but I need help to understand. In the following code myArray has its content at label "A" but is empty at label "B". The purpose of the code is to read multiple csv files, store some values from each of the files and use myArray later in the script. I know there must be something with vars in the Ajax request (.get). Thanks
var myArray = [];
var lines = [];
$.each(fileNames, function(lineNo, file)
{
$.get(file, function(data)
{
lines = $.csv.toObjects(data);
$.each(lines, function(lineNo, line)
{
... code ...
myArray.push(someValue);
});
--- A ---
});
--- B ---
});

$.get is asynchronous.
Any code placed at B will run while the get is happening.
Place any code you want to act on MyArray inside the function supplied to get, or place another call inside the get function to act on your data.
$.get(file, function(data)
{
lines = $.csv.toObjects(data);
$.each(lines, function(lineNo, line)
{
... code ...
myArray.push(someValue);
});
// myArray is ready here. Place any code that acts on it here...
});
// myArray may not be ready here, since the `get` hasn't finished yet.

The problem is that the get callback gets executed asynchronously when the get request return, but the code below the get call gets executed right away, before the callback.
You could execute synchronously replacing get with ajax async=false. This will be a bit slower as each call would not begin till the previous one ended.
var myArray = [];
var lines = [];
$.each(fileNames, function(lineNo, file)
{
$.ajax({
url: file,
success: function(data) {
lines = $.csv.toObjects(data);
$.each(lines, function(lineNo, line)
{
... code ...
myArray.push(someValue);
});
},
async:false
});
});

If you don't like the async:false approach you could use this:
var myArray = [];
var lines = [];
var count = 0;
$.each(fileNames, function(lineNo, file)
{
$.get(file, function(data)
{
lines = $.csv.toObjects(data);
$.each(lines, function(lineNo, line)
{
... code ...
myArray.push(someValue);
});
}).done(function(){
count++;
if(count > fileNames.lenght){
// Code to use array goes here
}
});
});

Related

Reading file with Javascript into array - can't seem to make it work

I have a simple 2-column csv file that I would like my site to read and ultimately parse into an array. The data is in the following format:
Atlanta Braves, Atlanta_Braves
Baltimore Orioles, Baltimore_Orioles
Boston Red Sox, Boston_Red_Sox
etc.
The file is currently stored in the same location as my html file. I am trying to use an ajax request to pull the data from the file into an array, then parse further such that myArray[0][0] = 'Atlanta Braves'.
Here is my code:
var myArray = [];
$.ajax({
type: 'GET',
url: 'datafilename.csv',
success: function(data){processData(data);}
});
function processData(data){
myArray = data.split('\n');
for (i = 0; i < myArray.length; i++){
myArray[i] = myArray[i].split(',');
}
}
alert(myArray[0][0]);
Unfortunately, the alert only returns 'undefined'. What am I doing wrong here? Any feedback would be appreciated.
$.ajax is an asynchronous function. That means that it won't complete until sometime later, after your other synchronous code has already run. Try adding this:
function processData(data) {
// Your existing code goes here...
alert(myArray[0][0]);
}
This works because processData is only run after the AJAX call has returned. Asynchronous functions basically work like this:
var value = 1;
setTimeout(function() {
value = 2; // This won't happen for about 1 second
console.log(value); // 2
}, 1000); // Run this function in 1 second
console.log(value); // 1. This happens almost immediately, without pause

How to read XML data with $.ajax and return the value within a $.each loop

For one part of our study-project we need to compare an array of Strings with a xml database. So my idea was to divide in 2 parts (because we need the compare-function twice). First I loop through the array with $.each and then I pass the value to another function that makes an ajax request to the xml, compares the value with each data in xml and if something found, it pushes it to an array which should be returned at the end.
In one function the jquery.each() is called:
function doSomething(){
liste = ["test1","test32","test22"];
$.each(liste, function(index, value){
var checkIt = compareDataBase(value);
if(checkIt.length>0) //do Something
});
}
and this is the function that compares the value and returns an array:
function compareDataBase(foo){
var lists = [];
$.ajax({
type:"GET",
url: "data/database/datenbank.xml",
dataType:"xml",
success: function(xml){
$(xml).find('product').each(function(index, element){
var current_product = $(this).text();
if(current_product.indexOf(foo)>-1)lists.push(current_product);
});
},
error: function(){
console.log("Fehler bei Produkte auslesen");
}
});
return lists;
}
But sadly that doesn't work. "checkIt" is always undefined because it doesnt wait for the ajax...
I tried to use the $.when function or give the compareDataBase()-function a callback but somehow that didnt work neither (I think because
I declared it wrong)
So maybe someone knows how to make this right?
Thanks for your help!
br sebi
You should use callbacks (or promises which are a variation on callbacks), the following solution example uses callbacks:
function compareDataBase(foo, callback){
var lists = [];
$.ajax({
type:"GET",
url: "data/database/datenbank.xml",
dataType:"xml",
success: function(xml){
$(xml).find('product').each(function(index, element){
var current_product = $(this).text();
if(current_product.indexOf(foo)>-1)lists.push(current_product);
});
// notify the callback with the result lists here
callback(lists);
},
error: function(){
console.log("Fehler bei Produkte auslesen");
}
});
}
function doSomething(liste, index){
if ( index < liste.length )
{
compareDataBase(liste[index], function(checkIt){
if(checkIt.length>0) //do Something
// process next list item using callbacks
doSomething(liste, index+1);
});
}
}
// start the process
doSomething(["test1","test32","test22"], 0);
Note that the example solution processes each list item only after the previous item has been processed (it kind of synchronises the callbacks, each callback will call the next one). One can remove this feature and process all asynchronously as follows:
// process all async
var liste = ["test1","test32","test22"];
for (var i=0; i<liste.length; i++) doSomething([liste[i]], 0);

jquery to use .get and retrieve variables from text file

I have a list of names in a text file
example:
user1 = Edwin Test //first line of text file
user2 = Test Edwin //second line of text file
I would like each lines data to be set to a variable:
user1 and user2 //so that after jquery loads I can user $user1 and it will give Edwin Test
Text file will be in the same folder as jquery file.
My code:
$.get('users.txt', function(data) {
alert(data);
var lines = data.split("\n");
$.each(lines, function() {
var line=perLine[i].split(' ');
});
});
When i load the page using mamp locally, I am able to see the contents on the file using the alert but when i type for example (user1) in the console it says that the variable is not set.
Here's what I think you want:
$.get('users.txt', function(data) {
var lines = data.split("\n");
$.each(lines, function(i) {
var line = lines[i].split(' = ');
window[line[0]] = line[1];
});
});
later on...
console.log(user1); // "Edwin Test"
var users = {};
var lines = data.split("\n");
$.each(lines, function (key, value) {
var prep = value.split(" = ");
users[prep[0]] = prep[1];
});
To output user1 You would call users.user1
JSFiddle
The code adds lots of variables to the global namespace. Also, it invites bugs because $.get is asynchronous and so code that depends on the variables existing needs to be called where shown in the comment to be guaranteed to work. This would be considered bad style by many, but here's how to do it:
$.get('users.txt', function(data) {
alert(data);
var lines = data.split("\n");
var i,l=lines.length,parts;
for(i=0;i<l;++i){
parts = lines[i].split('=');
if (parts.length == 2){
try {
// window is the global object. window['x']=y sets x as a global
window['$'+parts[0]] = parts[1]; // call the var $something
} catch(e) {}; // fail silently when parts are malformed
}
// put any code that relies on the variables existing HERE
}
});
Here's what you might do instead:
Put the data in an object. Pass the object to a function showVars(vars) that contains the next step.
$.get('users.txt', function(data) {
alert(data);
var lines = data.split("\n");
var i,l=lines.length,parts, vars = {};
for(i=0;i<l;++i){
parts = lines[i].split('=');
if (parts.length == 2){
try {
vars[parts[0]] = parts[1];
} catch(e) {}; // fail silently when parts are malformed
}
showVars(vars); // put any code that relies on the variables existing HERE
}
});
function showVars(vars){
// put whatever uses/displays the vars here
}
Yet another way to make this easier to change the data format. If you can store the data in this format, called JSON:
['Edwin Test','Test Edwin','Someone Else','Bug Tester']
Then the parser is either a one liner array = JSON.parse(jsonString) or sometimes is done for you by jQuery and put in data. JSON can store all kinds of data, and there is support for it in other languages libraries besides Javascript, such as PHP, python, perl, java, etc.
$.get('users.txt', function(data) {
alert(data);
var lines = data.split("\n");
for(var i = 0 ; i < lines.length; i++){
var line=lines[i].split(' ');
});
});
I think you are missing the i in the loop.
I guess you could also do
$.each(lines, function(i) {
var line=lines[i].split(' ');
});
In any event, I would probably recommend that you do this string splitting on the server instead and deliver it to the client in the correct/ready form.

jQuery.each() and Array Manipulation

Here's my code:
$(document).ready(function() {
var myArray = [];
$.getJSON("some url",function(data){
$.each(data, function(){
myArray.push("a string" + this);
});
alert(myArray);
});
//alert(myArray);
});
The code as shown is working just fine and it displays the array and its contents.
However, when I try to display the array by having the command line right after the $.each code block (commented out in the sample code), the array and its contents are not displayed. An empty/ blank message is returned instead.
Why is this happening and how can I fix it? I'd like to have the command "alert(myArray);" right after the $.each block.
Thank you in advance!
var myArray = [];
var jqxhr = $.getJSON( "some url", function(data) {
$.each(data, function(){
myArray.push("a string" + this);
});
}) ;
jqxhr.complete(function() {
console.log(myArray);
});
jQuery XHR object, or "jqXHR," is returned by $.getJSON()
When the request is already complete, the .complete() callback is fired immediately.

jQuery .push into an Array in a .get call gives an empty result

Can anyone tell me why the below gives me an empty string? When I console.log(contentArray) in the $.get() callback function it shows the data but when I try to do it where it is in the code below, the result is empty.
sectionArray = [];
contentArray = [];
$(function () {
if (index == 1) {
$('menu:eq(' + (section - 1) + ') li a').each(function () {
sectionArray.push($(this).attr('href'));
});
var len = sectionArray.length;
for (var i = 0; i < len; i++) {
href2 = sectionArray[i];
$.get(href2, function (data) {
string = data.toString();
contentArray.push(string);
});
}
content = contentArray.toString();
console.log(content);
}
because ajax request ends after you call console.log() try this:
$.get(href2, function(data){
string = data.toString();
contentArray.push(string);
content = contentArray.toString();
console.log(content);
});
also do ajax request in loop is not best thing to do. that wont work as you want.
UPDATE:
also jQuery has async option set to false and your code should work but will work slow. Synchronous requests may temporarily lock the browser.
UPDATE 2
maybe try something like this(maybe not so good idea :D):
var countRequests = len;
$.get(href2, function(data){
string = data.toString();
contentArray.push(string);
countRequests = countRequests - 1;
if (countRequests == 0) {
content = contentArray.toString();
console.log(content);
// or create callback
}
});
The problem is that your $.get() ajax requests are executed asynchronously.
That is, the $.get() function returns immediately without waiting for the response, your entire for loop completes (queueing up multiple ajax requests), then your console.log() occurs at which point the array is still empty. Only after that do any of the ajax success handlers get called, regardless of how fast the ajax responses come back.
EDIT: Here is an answer from another question that shows how to do something after all the ajax calls have completed: https://stackoverflow.com/a/6250103/615754

Categories