JS and jQuery, global object gets empty when function is finished - javascript

I have a problem with an object dict. When json datas are received, program calls LoadDict() function, where dict object gets filled with new data from server. I used FireBug to make sure that dict has all new elements with correct information, but when function is finished, dict gets empty again like it was before ajax request. This code executes in the global scope:
var dict = new Dictionary();
function LoadDict(words) {
for (var i in words) {
var word = new Word();
word.word = words[i].Word;
word.transcript = words[i].Transcript;
word.frequency = words[i].Frequency;
word.meanings = words[i].Meanings;
word.examples = words[i].Examples;
word.imgLinks = words[i].ImgLinks;
dict.Add(word);
}
}
$.getJSON("getall").done(LoadDict);
dict.PrintDictionary);
And this is some code of my Dictionary class
function Dictionary() {
this.collection = new Array();
this.count = 0;
this.sorted = false;
}
Dictionary.prototype.Add = function(word) {
if (word instanceof Word) {
word.id = this.count;
this.collection[this.count] = word;
this.count++;
this.sorted = false;
}
}
Dictionary.prototype.PrintDictionary = function() {
function WordToString(word) {
var line = "<strong>" + word.word + "</strong> [" + word.transcript + "] - " + word.meanings[0];
for (var j = 1; j < word.meanings.length; j++) {
line += ", " + word.meanings[j];
}
return line;
}
var result = "<ol>"
for (var i = 0; i < this.collection.length; i++)
result += "<li>" + WordToString(this.collection[i]) + "</li>";
result += "</ol>"
document.write(result);
}
Declaration of Dictionary class goes before creating dict object.
Help, please!

A timing problem.
In your code, PrintDictionary function have excuted before ajax call is complete.

The problem is that the $.getJSON is async.
This means that the dict.PrintDictionary(); line gets executed before the result is returned from the getJSON call

Related

how to return this value from my function? is it wrong method?

I don't understand how to solve the following problem when return the value from nested function. is it wrong method. How can I get it?
My basic purpose is to get array values (all coordinates) from var mymap_coordinates, but it can't. that's why I use .toString() to test.
*<script>
mymap.on( //leftlet code
'contextmenu',
function (event)
{
var tg_marker = L.marker(event.latlng, {icon: treegroupIcon}).addTo(mymap);
store_coordinates[incre_coord] = new Point(tg_marker.getLatLng().lat.toFixed(8), tg_marker.getLatLng().lng.toFixed(8));
var n = store_coordinates.length;
var mymap_coordinates = abcdefg(store_coordinates, n);
window.alert (mymap_coordinates.toString()); //This alert can't print all array value when return the value from abcdefg function
incre_coord = incre_coord + 1;
}
);
function abcdefg(points, n)
{
.......
.......
.......
// return Result
var num = 0;
var map_coordinate = new Array();
for (let temp of abc.values())
{
map_coordinate[num] = "[" + temp.x + ", " + temp.y + "]";
num = num + 1;
}
window.alert (map_coordinate.toString()); //This alert can print all array value
return map_coordinate;
}
</script>*

JSON return value to global variable

Simply my code looks like this:
var thevariable = 0;
For(){
//somecode using thevariable
$.getJSON('',{},function(e){
//success and i want to set the returned value from php to my variable to use it in the forloop
thevariable = e.result;
});
}
my main problem that the variable value stays "0", during the whole For loop, while i only want it to be "0" at the first loop, then it takes the result returned from PHP to use it on for loop.
here it my real code if you need to take a look:
var orderinvoice = 0;
for(var i=0; i<table.rows.length; i++){
var ordername = table.rows[i].cells[5].innerText;
var orderqty = ((table.rows[i].cells[1].innerText).replace(/\,/g,'')).replace(/Qty /g,'');
var orderprice = (table.rows[i].cells[2].innerText).replace(/\$/g,'');
var ordertype = table.rows[i].cells[3].innerText;
var orderlink = table.rows[i].cells[4].innerText;
$.getJSON('orderprocess.php', {'invoice': orderinvoice, 'pay_email': email, 'ord_name': ordername, 'ord_qty': orderqty, 'ord_price': orderprice, 'ord_type': ordertype, 'ord_link': orderlink}, function(e) {
console.log();
document.getElementById("result").innerText= document.getElementById("result").innerText + "Order #"+e.result+" Created Successfully ";
document.getElementById("invoker").innerText = ""+e.invoice;
orderinvoice = e.invoice;
if(i+1 == table.rows.length){
document.getElementById("result").innerText= document.getElementById("result").innerText + "With invoice #" + e.invoice;
}
});
in a loop block, before one ajax complete other one will be run and this's javascript natural treatment. For your case you can call a function at the end of success event. Do something like this:
var i = 0;
doSt();
function doSt() {
var orderinvoice = 0;
var ordername = table.rows[i].cells[5].innerText;
var orderqty = ((table.rows[i].cells[1].innerText).replace(/\,/g, '')).replace(/Qty /g, '');
var orderprice = (table.rows[i].cells[2].innerText).replace(/\$/g, '');
var ordertype = table.rows[i].cells[3].innerText;
var orderlink = table.rows[i].cells[4].innerText;
$.getJSON('orderprocess.php', { 'invoice': orderinvoice, 'pay_email': email, 'ord_name': ordername, 'ord_qty': orderqty, 'ord_price': orderprice, 'ord_type': ordertype, 'ord_link': orderlink }, function(e) {
console.log();
document.getElementById("result").innerText = document.getElementById("result").innerText + "Order #" + e.result + " Created Successfully ";
document.getElementById("invoker").innerText = "" + e.invoice;
orderinvoice = e.invoice;
if (i + 1 == table.rows.length) {
document.getElementById("result").innerText = document.getElementById("result").innerText + "With invoice #" + e.invoice;
}
i++;
if (i < table.rows.length) doSt();
});
}
I think you need a recursive function that always deals with the first element in your rows array and then splices it off and calls itself. For example, something like this:
function getStuff(rows, results) {
if (rows.length > 0) {
var ordername = rows[0].cells[5].innerText;
$.getJSON('orderprocess.php', { 'ord_name': ordername }, function (e) {
// do some stuff
results.push('aggregate some things here?');
rows.splice(0, 1);
return getStuff(rows, results);
});
} else {
return results;
}
}
When the array is spent, results will be returned with whatever aggregate you wanted at the end of the cycle. Then, you can do as you please with the results. I think you can also manipulate the DOM inside the function as you see fit if that makes more sense. Hope this helps.

Array length remains 0 even though I push 'objects' to it

I have a little piece of code that reads some ajax (this bit works) from a server.
var self = this;
var serverItems = new Array();
var playersOnlineElement = $("#playersOnline");
function DataPair(k, v) {
this.key = k;
console.log("new datapair: " + k + ", " + v);
this.value = v;
}
DataPair.prototype.getKey = function() {
return this.key;
}
DataPair.prototype.getValue = function() {
return this.value;
}
$.getJSON("http://127.0.0.1", function(data) {
$.each(data, function(key, val) {
var pair = new DataPair(key, val);
self.serverItems.push(pair);
});
});
console.log(serverItems.length); //Problem is here
for (var i = 0; i < serverItems.length; i = i + 1) {
var dpair = serverItems[i];
if (dpair.getKey() === "playersOnline") {
self.playersOnlineElement.text("Players Online: " + dpair.getValue());
}
}
The datapair and the JSON get loaded but when they are pushed to the array it doesn't seem to work. I tried with self.serverItems and just serverItems because netbeans showed me the scope of the variables being good if I used just serverItems but I am a bit confused as to why this doesn't work. Can anyone help me?
I put in comments where the error is. serverItems.length is 0 even though when debugging in a browser in the DOM tree it has an array serverItems with all the data inside.
Assumingly this serverItems is in another scope and not the one I am calling when I want to get the length?
add this code into the success part, since its asynchronous...
for (var i = 0; i < serverItems.length; i = i + 1) {
var dpair = serverItems[i];
if (dpair.getKey() === "playersOnline") {
self.playersOnlineElement.text("Players Online: " + dpair.getValue());
}
to...
$.getJSON("http://127.0.0.1", function(data) {
$.each(data, function(key, val) {
var pair = new DataPair(key, val);
self.serverItems.push(pair);
for (var i = 0; i < serverItems.length; i = i + 1) {
var dpair = serverItems[i];
if (dpair.getKey() === "playersOnline") {
self.playersOnlineElement.text("Players Online: " + dpair.getValue());
}
});
});

setting callback property value to null

Im wondering in the following code, how could I set the callback property "value" to null?
The code takes a bunch of ids (31, 32 ,33) and then uses a callback function to monitor changes to values of these ids. When I run the code again using the same IDs, is there a way to set the callback property to null?
obsids = new Array();
function list() {
if (arguments.length) {
leng = arguments.length;
for (i = 0; i < leng; i++) {
obsids[i] = new LiveAPI(callback, "id "+arguments[i]);
obsids[i].property = "value";
}
}
function callback(args) {
outlet(0, args[0] + " " + args[1] + " " + this.id);
}
}
You will need a specific callback for each obsids[i], and you need to create them in a closure for not loosing i.
function list() {
var obsids = [];
for (var i=0, len = arguments.length; i < len; i++)
obsids[i] = createApi("id "+arguments[i]);
function createApi(id) {
var obsid = new LiveAPI(function callback(args) {
obsid.property = null;
outlet(0, args[0] + " " + args[1] + " " + this.id);
}, id);
obsid.property = "value";
return obsid;
}
return obsids;
}

Javascript methods recalling and printing

I'm studying JavaScript and I've some problems with the recall of functions...
These are my two functions:
the first:
function geisson() {
var iabile = new XMLHttpRequest();
iabile.onreadystatechange = function () {
if (iabile.readyState == 4) {
var objectjson = {};
var arrayCards = []; //creazione dell'array che conterrà le cards
objectson = JSON.parse(iabile.responseText);
arrayCards = objectson.cards;
var Ettore = []; //Vèttore di cards
//the results
for (i = 0; i < arrayCards.length; i++)
document.getElementById('image').src = "http://www.mysite.com/png/public/card/" + arrayCards[i].__guid__ + "?width=292";
}
}
iabile.open("GET", "gnekcard.json", true);
iabile.send(null);
}
and the second function:
function Entity() {
var iabile = new XMLHttpRequest();
iabile.onreadystatechange = function () {
if (iabile.readyState == 4) {
var objectjson = {};
var arrayCards = []; //creazione dell'array che conterrà le cards
objectson = JSON.parse(iabile.responseText);
arrayCards = objectson.cards;
//the results
for (i = 0; i < arrayCards.length; i++)
document.getElementById('informazioni').innerHTML += "\r\n" + "Nome : " + arrayCards[i].__title__ + "\r\n" + "Vanity url: " + arrayCards[i].vanity_urls[0] + "\r\n";
}
}
iabile.open("GET", "gnek.json", true);
iabile.send(null);
}
I would like to have a third function that prints the results of the other 2 functions. I'd prefer to have the "for" in only in the third function and recall the vectors of the others methods but they aren't global. I don't want to have global variables (if possible) so how can I do it?
In the geisson function you can do this:
geisson.arrayCards = arrayCards;
and you can do the same in the Entity function
Entity.arrayCards = arrayCards;
Then you can create a third function that can access the arrayCards of each function.
function displayArrayCards {
var geissonCards = geisson.arrayCards;
var EntityCards = Entity.arrayCards;
var i;
for(i = 0; i < geissonCards.length; i++) {
document.getElementById('image').src = "http://www.mysite.com/png/public/card/" + geissonCards[i].__guid__ + "?width=292";
}
for(i = 0; i < EntityCards.length; i++) {
document.getElementById('informazioni').innerHTML += "\r\n" + "Nome : " + EntityCards[i].__title__ + "\r\n" + "Vanity url: " + EntityCards [i].vanity_urls[0] + "\r\n";
}
}
Do what you should always do when you work with Ajax calls: Use callbacks.
For example:
function geisson(callback) {
var iabile = new XMLHttpRequest();
iabile.onreadystatechange = function () {
if (iabile.readyState == 4) {
// ...
callback(objectson.cards);
}
}
iabile.open("GET", "gnekcard.json", true);
iabile.send(null);
}
and in your third function:
function someName() {
geisson(function(data) {
for (var i = 0; i < data.length; i++) {
//... do something with data ...
}
});
// call Entity the same way here...
}
Btw, in your first function, you always override the src property of the same element (document.getElementById('image')). It does not make sense to iterate over the whole array here, sine eventually, src will have the value related to the last element. Either assign the values to multiple elements or just get the last element in the array.

Categories

Resources