Passing variables between functions - javascript

I have two functions, one that makes an Ajax request when the user loads the page, and one that will run every 5 or so seconds to update something. Using the first function, I can output a variable that I need to use in the second function.
function insert_last_ten() {
$.ajax({
url: 'freeshout/chatlog.php',
success: function(data) {
$("#inner-wrap").html(data);
var first_child = $("#inner-wrap :first-child").html();
var value = first_child.match(/(value)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?/);
var realtime = value[2];
}
});
}
Basically, I need to use realtime to do something else in another function. For the sake of simplicity, let's pretend this is the second function:
function update() {
alert(realtime);
}
How could I go about making that work?

In the success callback, cancel the timeout and start a new one using the updated value. You can pass the timeout identifier to insert_last_ten via argument and the success callback will pick it up via closure:
function createUpdateTimer(value, interval) {
return setTimout(
function () {
alert(value); // The created function knows what value is due to closure
}, interval);
}
function insert_last_ten(timer) {
$.ajax({
url: 'freeshout/chatlog.php',
success: function(data) {
$("#inner-wrap").html(data);
var first_child = $("#inner-wrap :first-child").html();
var value = first_child.match(/(value)=["']?((?:.(?!["']?\s+(?:\S+)=|[>"']))+.)["']?/);
var realtime = value[2];
cancelTimer(timer); // This callbac knows what timer is due to closure
timer = createUpdateTimer(realtime, 500);
}
});
}
// Start the timer:
var timer = createUpdateTimer('initial value', 500);
// Make ajax request:
insert_last_ten(timer);
Note that I am only beginning to familiarize myself with the good parts of JavaScript. This code is untested.

Related

Unexpected behavior with "SetInterval" in JavaScript

I have a JavaScript that makes request to a servlet. The request works but I can't get it to repeat at the specified time interval of 1 sec. What am I doing wrong?
I am quite new to front-end development and JavaScript.
$(document).ready(function() {
$('#userName').blur(function(event) {
var name = $('#userName').val();
setInterval($.get('JqueryServlet', {
userName : name
}, function(responseText) {
$('#ajaxResponse').text(responseText);}), 1000);
});
});
setInterval works with the arguments setInterval(callbackFunction, timingInMilliseconds).
It looks like you are putting your call to $.get directly in the callbackFunction argument. This unfortunately doesn't work as the result of your call to $.get is passed as the argument, not the function itself. Even if you did pass the function, it wouldn't be called with the proper arguments.
Instead wrap it in an anonymous function call or place it in a function, like so:
function getServlet() {
// code
}
setInterval(getServlet, 1000); // to go off every 1 second
Or:
setInterval(function() {
// code
}, 1000);
If you insisted on using $.get directly in setInterval, you could use something like:
setInterval(function(a,b,c){
console.log(a + b +c);
}, 500, "a", "b", "c");
In most browsers (see the link above) you can use setInterval with the call:
setInteval(callbackFunction, timingInMilliSeconds, callbackArg, callbackArg, ...);
Anything you want to do, put inside of this block below:
setInterval(function(){
alert("I will be called in 3 second and again after 3 seconds");
}, 3000);
Try it now with this:
$(document).ready(function() {
$('#userName').blur(function(event) {
var name = $('#userName').val();
setInterval(function(){
$.get('JqueryServlet', {
userName : name
}, function(responseText) {
$('#ajaxResponse').text(responseText);
});
}, 1000);
});
});
on any blur event you create new instance of interval and they remain in memory and can cause conflict ,create a global interval ref object and set interval reference to it and before start new interval dispose old interval.

Functions with dynamic parameters in javascript

I use this function to retrieve an array from a web service.
button.onclick = function(item) {
var nonReplying = new Array(getNoreply(item));
console.log(nonReplying);
setTimeout(unInviteUsers(item, nonReplying), 2500);
}.bind(button, EventsArray[i][1]);
Then the function
function unInviteUsers(event,nonReplying)
{
//remember to parseInt() the first param, Event ID as well
for(var i = 0; i <= nonReplying.length; i++)
{
unInvite(event,parseInt(nonReplying[0][i].replace('"','').replace('"','')),AccessToken);
}
}
calls this function
function unInvite(event, user)
{
$.ajax({
url: 'https://graph.facebook.com/'+event+'/invited/'+user+'?access_token='+AccessToken,
type: 'DELETE',
success: function(result)
{
console.log(JSON.stringify(result));
}
});
}
But when button.onclick gets triggered some how the array nonReplying is not passed and unInviteUsers() returns
TypeError: 'undefined' is not an object (evaluating 'nonReplyingArray[0][i].replace')
And by the way, how do I properly force a function to wait until an other function is fully finished?
Is nonReplying actually a two-dimensional array?
Also, aside from the undefined error,
setTimeout(unInviteUsers(item, nonReplying), 2500);
will not do what you want. I believe you want that unInviteUsers to fire after 2.5 seconds. The first parameter of setTimeout needs to be a reference to a function. Unless unInviteUsers returns an anonymous function itself, this won't do the trick, but this might:
setTimeout(function() { unInviteUsers(item, nonReplying) }, 2500);

Get a value from FB.api with a callback?

I have one simple question, been searching on Stack Overflow there are some questions on this topic but can't get a working solution.
I have a simple function for getting number of page likes on Javascript SDK:
function getLikes(div, graf) {
var numblike;
FB.api(graf, function(response) {
var numblike = response.likes;
$(div).prepend(numblike);
});
return numblike; // can't get it to return
}
var pLike = getLikes ("#mydiv", /app_id); // always undefined
Function works and it pre-pends the right number to my div but return always sets my variable to undefined. I understand that the script runs asynchronous and I need to use a callback function but I just can't get it right.
This is called javascript event loop. you can't return numblike from the function cause it's set only in the callback of FB.api.
So you can do similar to that - just send callback:
function getLikes(div, graf,callback) {
FB.api(graf, function(response) {
var numblike = response.likes;
$(div).prepend(numblike);
callback(numblike);
});
}
getLikes ("#mydiv", /app_id,function(numblike){
alert(numblike);
}); // always undefined
You have decalred numblike two times, just remove var declaration in the second one:
function getLikes(div, graf) {
var numblike;
FB.api(graf, function(response) {
numblike = response.likes; // var removed
$(div).prepend(numblike);
});
return numblike;
}

jquery execute function when two conditions are met

I need to execute a specific function mvFinishItUp() when two conditions are met. More specifically, one condition is the callback success of a $.ajax the other is a normal flow of the code until it reaches the function. Kinda of this:
$.ajax({
url: mv_finalUrl,
success: function (data) {
mvFinishItUp(data);
},
dataType: 'html'
});
/* here a lot more code, with animations and some delays */
mvFinishItUp(data) {
/* My function code */
/* But this code must only run after it has been called via the call back
and after all the other code has been ran as well */
}
So, the function must wait for all the code if the ajax callback is quicker, or the other way around. Any ideas on how this could be implemented?
I'm willing to change the whole concept of script code, as I believe the loose code between the ajax, and the function itself should go to a function aswell ...
This is a perfect use case for jQuery Deferred objects.
Remove the success: parameter from the AJAX call, and register the handler later:
var jqxhr = $.ajax(...);
// do some other synchronous stuff
...
// and *then* register the callback
jqxhr.done(mvFinishItUp);
Deferred objects cope perfectly well (by design) with being registered on an AJAX event after that event already finished.
Try like below, (It is just psuedo code)
var isAJAXDone = false, isFunctionCodeDone = false;
$.ajax({
//..
success: function () {
isAJAXDone = true;
mvFinishItUp(data, isAJAXDone, isFunctionCodeDone);
}
});
//..Your function code
//..Add this below the last line before the function ends
isFunctionCodeDone = true;
mvFinishItUp(data, isAJAXDone, isFunctionCodeDone);
//..
mvFinishItUp(data, isAJAXDone, isFunctionCodeDone ) {
if (isAJAXDone && isFunctionCodeDone) {
//Do your magic
}
}
Maybe something like this would do the trick:
var _data = undefined;
$.ajax({
url: mv_finalUrl,
success: function (data) {
_data = data;
myFinishItUp(data); // call the function from here if it's faster
},
dataType: 'html'
});
/* here a lot more code, with animations and some delays */
function myFinishItUp(data) {
this.data = data; // store the data from the AJAX call or the code, whichever reaches first
// if the code reaches this before the AJAX call completes, data will be undefined
if(typeof this.wasCalled == "undefined") {
/* My function code */
/* But this code must only run after it has been called via the call back
and after all the other code has been ran as well */
this.wasCalled = true;
}
}(_data); // function that calls itself when the code gets to this point with a self-contained boolean variable to keep track of whether it has already been called
I used a self calling function execute when the code flow gets to that point, but if it's called from the AJAX call, it won't execute. It keeps track of whether or not it's already been called with a self-contained boolean value.
Here I add an second parameter to check callback check
function mvFinishItUp(data, byCallback) {
var iscallback = byCallback || false; // if you don't send byCallback
// default will false
if(iscallback) {
// execute if called by callback
}
}
success: function (data) {
mvFinishItUp(data, true); // call with second parameter true
},
To execute mvFinishItUp() after ajax done and all codes between ajax and mvFinishItUp finished you can do something like this:
var allFunctionExecuted = false; // global to detect all code execution
$.ajax({
url: mv_finalUrl,
success: function (data) {
mvFinishItUp(data, true);
},
dataType: 'html'
});
function func1() {
}
function func2() {
}
// some other code
function func3() {
allFunctionExecuted = true;
}
Now,
function mvFinishItUp(data, byCallback) {
var iscallback = byCallback || false; // if you don't send byCallback
// default will false
if(iscallback && allFunctionExecuted) {
// execute if ajax done
// and others code done
}
}
This is very "ugly" code, but you can modify it to not use global vars, so this is just illustrative:
var ajaxExecuted = false,
codeExecuted = false;
$.ajax({
url: mv_finalUrl,
success: function (data) {
ajaxExecuted = true;
mvFinishItUp(data);
},
dataType: 'html'
});
/* here a lot more code, with animations and some delays */
codeExecuted = true;
mvFinishItUp(data) {
/* My function code */
if(ajaxExecuted && codeExecuted) {
/* But this code must only run after it has been called via the call back
and after all the other code has been ran as well */
}
}
I just added two flags: ajaxExecuted and codeExecuted, and inside the function an if statement that checks the value of the those flags, and executes only when the two of them are set to true. So no mather who calls it first, it get only executed when the two flags are set to true.
A cleaner way could be to implement the function in an object, and use properties instead of global vars.

jquery plugin functions return values

I stripped all my logic out of my jquery plugin for this question, but my problem is that when I call my function checkValidationName, it does it's thing and sets name = to true. Then when i try to compare it right after where i called it, the value is false. Why is this?
(function($){
$.fn.validate = function() {
var name = false;
$('.submitBtn').click(function() {
$.fn.validate.checkValidationName(nameValues);
**console.log("name = "+name); **//but this prints out "false"****
//shouldn't this be true since name returned true in the actual function??
}
});
$.fn.validate.checkValidationName = function(id) {
$.post("PHP/submitButtonName.php", {checkValidation: id},
function(data) {
**console.log("name = "+name); **//this prints out "true"****
//name is equal to true here
}, "json");
};
}
})(jQuery);
That's because the AJAX requests are asynchronous and right after you called checkValidationName, it hasn't finished yet. You need to do the comparison in the callback.
You can make checkValidationName take a callback and call it with the result when validated:
(function($){
$('.submitBtn').click(function() {
$.fn.validate.checkValidationName(nameValues, function(valid) {
console.log(valid);
});
});
$.fn.validate.checkValidationName = function(id, callback) {
$.post("PHP/submitButtonName.php", {checkValidation: id},
function(data) {
var valid = data.foo; // or however you determine that
callback(valid); // call callback
}, "json");
};
}(jQuery));
It's because the call to $.post() in checkValidationName is asynchronous. When you invoke the following line...
$.fn.validate.checkValidationName(nameValues);
Execution continues to the next line almost right away -- long before you get a result fro $.post(), at any rate.

Categories

Resources