Variable has different values inside and outside a function - javascript

I'm trying to set the value of an ID in the variable newID.
To "fill" the variable I'm reading a model like this:
press: function() {
var newID = 0;
oModel.read("/Delivery", null, null, true, function(oData) {
newID = oData.results[oData.results.length - 1].ID;
console.log(newID);
}
console.log(newID);
}
The first console.log gives me the value that I want, but the second one gives me 0 (the first condition set). I've tried using the incremental operator += and using this.newID but all in vain.
It really is a silly problem, probably something the way I'm calling newID on the console or the way I increment it inside the function...
Thanks in advance.

This was going to be a comment but it is so huge, so take it as a comment:
It is possible that the oModel.read function is asynchronous so when you execute the code basically that happen is this:
1) You declare the variable as 0.
2) You execute read function.
3) You execute console.log(var) => this print 0. (Because read does not finished yet and it is still 0 at this point).
4) Read function finished it work assign the desired value to var and execute console.log(var) => this print the desired value.
If that is the case you can implement something like this:
var press = function() {
var newId = 0;
function callback() {
console.log(newId);
}
oModel.read("/Delivery", null, null, true, function(oData) {
newID = oData.results[oData.results.length - 1].ID;
console.log(newID);
callback();
}
}

Related

Set global variable within anonymous function

I want to query a value from a script and use the value as variable for further functions. This code returns zero despite a value is set.
var total = 0;
var jqxhr = $.getJSON("number.php?jsonp=?", function(data) {
total = data[0]['Total']; // e.g 1234567
});
alert (total); // gives zero
I read that the problem could be with the asynchronous call and that my alert is executed before the anonymous function. I also tried to use some kind of setter function but withous success.
How can I set the global variable total?
Edit:
I now tried to use deferred objects / promises. I still have the problem that I need the value from the AJAX call before I initialise my counter. I cannot create the counter object in the done section because I cannot later change the value of the counter (still no global variable). Currently I have this:
var counter = $('.counter').jOdometer({
counterStart: '0',
numbersImage: '/img/jodometer-numbers-24pt.png',
widthNumber: 32,
heightNumber: 54,
spaceNumbers: 0,
offsetRight:-10,
speed:10000,
delayTime: 300,
maxDigits: 10,
});
function update_odometer() {
var jqxhr = $.getJSON("/number.php?jsonp=?")
.done(function(data){
console.log(data);
total = data['Total'];
counter.goToNumber(total);
})
.fail(function(data){
console.log(data);
});
};
update_odometer();
setInterval(update_odometer, 60000);
If I initialize the counter with zero then there is a strange start animations which jumps up and down. If I could get the real number instead of zero everything would work fine. Or should I completely switch to a synchronous call? How would I do that? Or are callbacks the better solution?
Took me a while to understand your problem. Still I'm not sure whether this would help or not.
var counter = null;
function update_odometer() {
var xhr = $.getJSON("/number.php?jsonp=?").done(function(data) {
if (counter === null) {
var counter = $('.counter').jOdometer({
counterStart: data['Total'],
numbersImage: '/img/jodometer-numbers-24pt.png',
widthNumber: 32,
heightNumber: 54,
spaceNumbers: 0,
offsetRight:-10,
speed:10000,
delayTime: 300,
maxDigits: 10,
});
} else {
counter.goToNumber(data['Total']);
}
});
}
If I were you I would look into library code and rectify the strange animation for zero start value. And I understand that you are not afraid to do that.

Loop a function using timeout and pass variables

Alright I have a feeling this is simple and I'm overlooking something.
I have an array of data that I'm passing into the function containing 300 rows.
The function itself picks out a random box to update, and a random array element to pass (0-299) and then updates that box.
The first Iteration is fine. The second returns "Uncaught ReferenceError: rand_ad is not defined "
function loop(last_ad, last_ad_box, ads_array){
// start
while(rand_ad == last_ad){
var rand_ad = get_rand(299);
}
while(rand_ad_box == last_ad_box){
var rand_ad_box = get_rand(29);
}
console.log(ads_array[rand_ad]);
// update the ad
// update_ad('.addno-'+rand_ad_box, ads_array[rand_ad]);
//recall itself to continue looping after 1 second
t = setTimeout("loop(rand_ad, rand_ad_box, ads_array)",3000);
}
function get_rand(max){
var rand = Math.floor(Math.random()*max) + 1;
return rand;
}
I think it might be the quotation marks around the function loop, that it's treating the variables inside as strings instead of actual variables, but I can't get it to render out before it snaggs the error.
Any ideas?
Your guess is correct. Change the timeout line to this:
t = setTimeout(loop, 3000, rand_ad, rand_ad_box, ads_array);
Passing strings to setTimeout is a security risk and not recommended. Also, it doesn't execute the code until the timeout occurs, so the variables are dereferenced after the function has exited.
If you need it to work in IE, then you'll have to use this:
t = setTimeout(function () {
loop(rand_ad, rand_ad_box, ads_array);
}, 3000);

update numeric variables when changed in prototype function

I am trying to add two numbers but for some reason I am not getting NaN.
Following is the sample code
function Slider(container, nav, pagination){
this.articleWidth = this.div.width() + 20;
this.divWidth = 960;
this.articleMargin = 0;
this.pageMargin = this.divWidth + this.articleMargin
}
Slider.prototype.articleTransition = function(pageNum){
var currArticle = pageNum -1;
this.articleMargin = currArticle * this.articleWidth;
this.container.animate({'margin-left': -this.articleMargin});
}
Here everything works as expected. But this.pageMargin is always 0 even though this.articleMargin's value is changing in the articleTransition function. And when I console log this.pageMargin is says NaN. I am trying to change value of this.articleMargin's value, everytime it is being invoked in the function.
Here is how I am invoking the function in my HTML.
var slider = new Slider($('div#contentSleeve'), $('a.anav'), $('ul#scroller li'));
slider.pagination.live('click', function(){
slider.articleTransition($(this).data('num'));
});
I guess that's because you are calling in anonymous function scope. Try like this:
slider.articleTransition.call(slider, $(this).data('num'));
I did fix this. All I had to do was to create a global variable that will store the value of both pageMargin and ArticleMargin.

Javascript - getting return value for setTimeout in recursive function

I have a recursive function which contains some drawing code inside. I was advised to use setTimeout as my drawing was not being displayed until the end of exection. First I put just the drawing code inside setTimeout but this did not help, however when I put the main recursive loop inside setTimeout the drawing worked perfectly, as shown below.
However I need to use the return value of setTimeout (i.e. state as shown below). How can I get this return value when using setTimeout, or solve this problem in another way.
var doLearning = function(time, observedData, state, domain, sampleAction, selectModel, numSamples, depth, discount, stateQueries) {
if(stateQueries[0](time, state) === true) {
console.log("New Round");
var currentModel = selectModel(observedData, 10, stateQueries);
var bestAction = sparseSampleMcmc(depth, numSamples, discount, currentModel, state, sampleAction, stateQueries);
var newStateReward = domain.executeAction(bestAction, stateQueries);
observedData.push(bestAction, newStateReward[1], newStateReward[0]);
console.log(time);
setTimeout(doLearning, 100, time + 1, observedData, newStateReward[0], domain, sampleAction, selectModel, numSamples, depth, discount, stateQueries);
} else {
console.log("Game Over");
return state;
}
}
Make an object with all your vars, like:
var game = {
time: ... ,
observedData: ....,
state: .... etc
}
In doLearning get and modify this object's properties when necessary:
var doLearning = function(obj) {
if(obj.state == ....)
obj.currentModel = whatever...
obj.bestAction = whatever...
setTimeout(function() { doLearning(obj) }, 100)
else
game over
}
This gives me the willies to say, but what if you had a global variable where the return value would go? Set it at the end of doLearning, Then when you detect that the timeout/drawing is done, check the global.
Without all the code I'm having a hard time understanding, but perhaps it would be better to use setInterval here is a simple example.
function draw(){
var state=//whatever
var num = setInerval(doLearning,100)
function doLearning(){
//You have access and can modify state and do not need to return its value
if(){}
else{
clearInterval(num);
console.log('Game over');
}
}
}
By calling as follows, the current execution context (ie. the environment of the current instance of doLearning) forms a closure in which time, observedData etc. remain available to the anonymous function defined inside the setTimeout() statement.
Thus, the following should work:
setTimeout(function(){
doLearning(time + 1, observedData, newStateReward[0], domain, sampleAction, selectModel, numSamples, depth, discount, stateQueries);
}, 100);

remembering a javascript var each call to function

I've got a nice little shopping basket where if the user deletes an item, the slideup jquery function is called and is disappears.
In the back ground, I'm removing it from the db with a call to a code igniter controller.
function delete_booking(id_booking, amount) {
if (user_total == null || user_total == '') {
var user_total = parseFloat(0);
}
$.ajax({
type: "POST",
data: '',
url: "/"+id_booking,
});
$("#booking_id_"+id_booking).slideUp();
var user_total = (parseFloat() - parseFloat() - parseFloat(user_total));
alert(user_total);
alert(parseFloat(user_total));
$('#booking_total').html(user_total);
}
What I can't fathom, is when I update the user total: $('#booking_total')
I need somehow to have the function remember the NEW total...
I've googled 'remembering JavaScript var' and similar, but I can't find exactly what I need...
My only other option is to do another call to the db with ajax to get the new total, but there MUST be a JS way to do this?
If you are not navigating to a different page, you can store the value in a variable that is outside the function (whether just on the page in the global namespace or the within the module in which the function resides).
var total;
function delete_booking(...)
{
...
total = user_total;
}
as you have said
I need somehow to have the function
remember the NEW total
a function cant remember a value, while a variable can, to solve your problem do one the below
1
var finalTotal;
function delete_booking(...)
{
//your more codes
$('#booking_total').html(user_total);
finalTotal = user_total;
}
now variable finalTotal hold the value
2
whenever you feel that you need to access the total read this way
var total=parseint($('#booking_total').html(),10) || 0;
But think method 1 is better than method 2
Because I "hate" a global approach for this type of problem, here is a little closure which will do the job of "remembering" the value (although I'm not really sure what exactly should be saved...^^)
var delete_booking = (function() {
var booking_total = $("#booking_total"),
total_amount = parseFloat(booking_total.html()) || 1000; // what ever the value should be...
return function(id, m) {
$.ajax(/* ... */);
$("#booking_id_"+id).slideUp();
total_amount -= m;
booking_total.html(total_amount);
}
}());

Categories

Resources