jquery plugin functions return values - javascript

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.

Related

Using setTimeout and recursion to see if something is "ready"?

I'm trying to figure out a good way to check if some asynchronous call is "ready" or not. I have some function that runs $.ajax, and in the callback function sets a boolean variable in the global scope to true (along with some other stuff). Before the ajax call, that boolean variable is false.
I want another function that retrieves that "other stuff." Since the ajax call is asynchronous, clearly I can't just immediately go retrieving it because it probably won't be there yet. That's where this boolean variable comes in. I'm thinking I can just check if that boolean is true every 100ms, and when it is, THEN go retrieve and return the "other stuff".
Code-wise, it looks something like this:
window.FOO = window.FOO || {};
;(function() {
var isReady = false;
var stuff;
$.ajax({
...
success: function(data) {
stuff = data;
isReady = true;
}
})
FOO.getStuff = function() {
// How to check if it's "ready"?
};
}
... (somewhere else)...
var stuff = FOO.getStuff();
I've tried the following for FOO.getStuff to no avail, because (I think) setTimeout is asynchronous:
FOO.getStuff = function() {
if (isReady) {
return stuff;
}
var theStuff;
setTimeout(function() {
theStuff = FOO.getStuff();
}, 100);
return theStuff;
};
Using the console, I can see it doing the right thing... but the first FOO.getStuff call returns before the subsequent ones do.
Is there a better way of doing this?
Edit: To clarify, I want the ajax call to remain asynchronous. I'm perfectly fine with the getStuff() calls being synchronous, because the ajax call will be very fast, and in most cases, getStuff() will be called later (after the used does some things).
Per your comments I have your answer. To solve async problem we should do async actions.
var stuff;
var stuffQueue = [];
$.ajax({
success: function(data) {
stuff = data;
if( stuffQueue.length > 0 ){
for(var i in stuffQueue){
var callback = stuffQueue[i];
callback(stuff);
}
stuffQueue = [];
}
}
});
function getStuff(callback){
//stuff has been loaded?
if( stuff ){
callback(stuff);
}else{
stuffQueue.push(callback);
}
}
To get stuff invoke:
var something = getStuff(function(stuff){
console.log(stuff);
});
This should solve your use case. Let me tell you more info, I have a JavaScript template engine, not yet open source but I have been using in professional projects, and I load all the templates with just one HTTP request, I made that request async:false because it is a dependence of the project.
There are reads that said that async false is evil, I do not believe so, what is evil is to use it wrong. Loading a templates file master, is a good example where async:false could work.
Additional I recommend you to read about promisses:
http://www.html5rocks.com/en/tutorials/es6/promises/
similar idea with Danie Aranda, I'd like to sugget you use custom event.
var isReady = true;
$.ajax({
beforeSend: function() {
isReady = false;
},
success: function(data) {
isReady = true;
$(document).trigger('display-stuff', data);
}
});
Foo.getStuff = function(data) {
if (!isReady) {
$(document).one('display-stuff', Foo.getStuff);
return;
}
// do something
};

Getting caller name during ajaxSend or ajaxSuccess

I want to extend all of my application's ajax calls with some special case handlers and be able to refire the method that started the ajax call if I need to. The problem I am having is I cannot get the name of the calling function that triggered the ajax call from my anonymous function event handlers, either ajaxSend or ajaxSuccess. I have tried all of the variations of caller/callee that are commented below plus many others. Here is some sample code:
var ajaxcaller;
$(document).ajaxSend(function(event,xhr,settings){
// Before we fire off our call lets store the caller.
// ajaxcaller = arguments.callee.caller.name;
//alert("get caller:"+arguments.callee.caller.name);
//alert("get caller:"+caller.name);
//alert("get caller:"+this.caller.toString());
//alert("get caller:"+event.caller.toString());
});
$(document).ajaxSuccess(function(event,xhr,settings){
var xobj = $.parseJSON(request.responseText);
if(xobj.ReFire === 1){
//Successful ajax call but not results we expected, let's refire
//Fix some params automagically here then
//SOME CODE HERE THAT Refires my caller
}
});
$(document).ajaxError(function(event,xhr,settings){
var xobj = $.parseJSON(request.responseText);
if(xobj.ReFire === 1){
//Fix some params automagically here then
//SOME CODE HERE THAT Refires my caller
}
});
Here's an idea, however I am not sure how reliable it would be, but you could intercept jQuery.ajax calls and append a caller property to the options that would reference the calling function as well as an args property that would reference the arguments that were passed to that function.
I am sure that if you play around with that idea, you will find a solution to your problem. If you don't like the idea of overriding jQuery.ajax, you could simply make sure to pass those references as options in all your ajax calls.
DEMO: http://jsfiddle.net/zVsk2/
jQuery.ajax = (function (fn) {
return function (options) {
var caller = arguments.callee.caller;
options.caller = caller;
options.args = caller.arguments;
return fn.apply(this, arguments);
};
})(jQuery.ajax);
$(document).ajaxSend(function (e, xhr, options) {
console.log('caller', options.caller);
console.log('args', options.args);
});
function getRecords(someArgument) {
return $.ajax({
url: '/echo/json/',
dataType: 'json',
data: {
json: JSON.stringify({ test: someArgument})
}
});
}
getRecords(1);
getRecords(2);

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.

Javascript module pattern, ajax functions callbacks

var ajaxStuff = (function () {
var doAjaxStuff = function() {
//an ajax call
}
return {
doAjaxStuff : doAjaxStuff
}
})();
Is there any way to make use of this pattern, and fetch the response from a successful ajaxcall when calling my method? Something like this:
ajaxStuff.doAjaxStuff(successHandler(data){
//data should contain the object fetched by ajax
});
Hope you get the idea, otherwise I'll elaborate.
Two things:
1. Add a parameter to the doAjaxStuff function.
2. When invoking doAjaxStuff, pass in an anonymous function (or the name of a function)
var ajaxSuff = (function () {
var doAjaxStuff = function(callback) {
// do ajax call, then:
callback(dataFromAjaxCall);
}
return {
doAjaxStuff : doAjaxStuff
}
})();
// calling it:
ajaxStuff.doAjaxStuff(function(data){
//data should contain the object fetched by ajax
});
Just let doAjaxStuff accept a callback:
var doAjaxStuff = function(callback) {
// an ajax call
// Inside the Ajax success handler, call
callback(response); // or whatever the variable name is
}
Depending on your overall goals, you could also use deferred objects instead (or in addition). This makes your code highly modular. For example:
var doAjaxStuff = function() {
// $.ajax is just an example, any Ajax related function returns a promise
// object. You can also create your own deferred object.
return $.ajax({...});
}
// calling:
ajaxStuff.doAjaxStuff().done(function(data) {
// ...
});
I believe you need to read the jQuery docs for jQuery.ajax. You could make a call as simple as:
$.ajax('/path/to/file').success(function (data) {
doStuff();
})

Access array returned from a function - javascript/jquery noob moment

When the form is submitted, I'm calling a function getPosts and passing through a variable str. What I'd like to do is get the data returned from that function.
// when the form is submitted
$('form#getSome').submit(function(){
var str = $("form#getSome").serialize();
var something = getPosts(str);
* This is where I'd like to get the data returned from getPosts()
return false;
});
// get the data
function getPosts(str){
$.getJSON('http://myurl.com/json?'+str+'&callback=?',
function(data) {
arrPosts = new Array();
$.each(data.posts, function(i,posts){
// build array here
});
return arrPosts;
});
};
I've tried many things, but have only gotten 'undefined' returned. I've tried console.log(something);, console.log(getPosts).
I'm missing something very fundamental here. Any help would be greatly appreciated.
EDIT:
What I'm trying to do is create a single function that would get posts. Then different events would call that function. I could then use that data. So one event may be submitting a form, another may be clicking a link, another lazy/endless scrolling. All could use the same getPosts function.
There's a lot of parsing out the results which amounts to a lot of lines of code. Was just trying to find a way to reuse that function. Do you think that would be possible?
$('a.thisLink').click(function(){
getPosts();
get the return from getPosts() and do something with it
});
$('form.thisForm').submit(function(){
getPosts();
get the return from getPosts() and do something with it
});
function getPosts(){
get the posts and return an array
}
Ajax requests are executed asynchronously, the callback function (function (data)) of getJSON is executed when the request ends, and returning a value in that callback has no effect, because is a nested function inside getPosts and its return value is never used.
Actually in your example, getPosts doesn't return anything and it ends its execution before the data is returned.
I would recommend you to work on your submit event handler, if you want to keep the getPosts function, you can introduce a callback parameter:
$('form#getSome').submit(function(){
var str = $("form#getSome").serialize();
getPosts(str, function (data) {
var array = [];
$.each(data.posts, function(i,posts){
// build array here
array.push(/* value to add */);
});
// array ready to work with...
//...
});
return false;
});
function getPosts(str, callback){
$.getJSON('http://myurl.com/json?'+str+'&callback=?', callback);
}
Edit 2: In response to your second comment, you could make another callback, that will be executed when the data has been processed by the first callback, and you can define it when you execute the getPosts function on the submit event handler:
$('form#getSome').submit(function(){
var str = $("form#getSome").serialize();
getPosts(str, reusableCallback, function (result) {
// result contains the returned value of 'reusableCallback' <---
});
return false;
});
function reusableCallback(data) {
var array = [];
$.each(data.posts, function(i,posts){
array.push(/* value to add */);
});
//...
return array;
}
function getPosts(str, callback, finishCallback){
$.getJSON('http://myurl.com/json?'+str+'&callback=?', function (data) {
finishCallback(callback(data)); // pass the returned value
// of callback, to 'finishCallback' which is
// anonymously defined on the submit handler
});
}
Edit 3: I think that the getPosts function and the "reusableCallback" function are strongly related, you might want to join them, and make the code easier to use and understand:
$('form#getSome').submit(function(){
var str = $("form#getSome").serialize();
getPosts(str, function (result) {
// result contains the processed results
});
return false;
});
function getPosts(str, finishCallback){
$.getJSON('http://myurl.com/json?'+str+'&callback=?', function (data) {
// process the results here
var array = [];
$.each(data.posts, function(i,posts){
array.push(/* value to add */);
});
//...
finishCallback(array); // when the array is ready, execute the callback
});
}
Your getPosts function looks incomplete, I'm no jquery expert but should it look something like:
function getPosts(str) {
$.getJSON('http://myexample.com/json?'+str+'&callback=?',function(data){
var arrPosts = [];
$.each(data.posts, function(i,posts){
... build array yada yada ...
});
return arrPosts;
});
}
The problem is that the $.getJSON callback function gets called when the get request returns the data, not inline with your function.

Categories

Resources