Do something after function is finished - javascript

I have a question, I think the answer will be simple, but I can't really find it ...
I have a function that creates content with ajax. After the function is finished I want to do something with the created content. To do that, I need to wait until all content is created, before I can do something with it.
What I prefer is something like this:
viewAllAccounts(function() {
//do something
});
or
viewAllAccounts().queue(function() {
// do something
});
But offcourse this is not going to work :)
I don't want to touch the viewAllAccounts function, because it is used multiple times in my app.
Is there a simple way to do something after a function is finished, not altering the function itself?
Thanks in advance!

when you invoke ajax calls with jquery, there are a bunch of handlers that fire when the ajax call completes. You should hook into those. Take a look-see at
http://api.jquery.com/jQuery.ajax/
particularly the 'success' and 'error' properties. just define functions for those and they will get called when the request completes.

For if you do not want to waste hundreds of bytes and a bunch of milliseconds on jQuery*:
You can create a second function:
function viewAllAccountsWithFinishingFunction(func) {
viewAllAccounts();
return func();
}
Then call:
viewAllAccountsWithFinishingFunction(function() {
//do something
});
* I do like jQuery, but using it for just one out of hundreds of features it has, I don't find it necessary.

Check out jQuery deferred objects:
http://www.erichynds.com/jquery/using-deferreds-in-jquery/
http://api.jquery.com/category/deferred-object/

Related

What is difference between calling a function and callback function?

What is the difference between following snippets
// calling a function
function execute(){
}
function fn(){
asynchronousFunction(function(){
execute();
})
}
fn();
How the below snippet is different from above
// callback a function
function execute(){
}
function fn(done){
asynchronousFunction(function(){
done();
})
}
fn(execute);
In which way callback is different from calling a function directly? What are pros and cons of each approach?
If you call a function, it will execute immediately.
If you pass the function as an argument to another function, then some other code will call it later (at which point it will execute).
They aren't different approaches for doing the same thing. You use a callback when you are writing a function that needs to do something at some point, but when what that something is depends on something outside the function.
The classic example is addEventListener. For the sake of discussion, let's limit ourselves to click events. You have a standard function for making something happen when something is clicked. Lots of programs want something to happen when something is clicked, but that something can be almost anything.
In first case, your function fn() can see execute() and the parameter is optional, because anytime you call fn() will be called execute().
in second case, you made your function more "general" and you may customize your callback function
The first option presents fn as a simple function that starts some kind of asynchronous action and doesn't present any other information to the outside. If fn is something like uploadData, then you'd have a simple function that tries to upload it (and maybe display an error message if it fails, or a success message when it's done), but the caller can only start it and do nothing else.
The second option additionally allows the caller of fn to decide what should happen when fn completes. So if fn is uploadData, then the caller is able to also specify what should happen once the data has been uploaded (or if there has been an error).
Callbacks like these gives you a lot of flexibility. In your second example, you are able to say: "Do fn(), and do the asynchronous function, and if you have finished, then call done()." And the point is, you can decide what done() does, although you have no insight in the method that calls it.
Delivering functions as an argument, that are to be executed e.g. at the begin, at the end or at other events, is a fundamental principle. It is the basis for hooks, callbacks, promises, configuring of complex objects etc.

Call a function after a bunch of other functions are complete

So I've got these functions:
function UrlExists(url){
$.ajax({
url: url,
success: function(data){
alert('exists');
},
error: function(data){
alert('fail');
}
});
}
function addScript(filepath, callback){
if (filepath) {
var fileref = document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", filepath);
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref);
}
if (callback) {
callback();
}
}
And then in my $(document).ready() I've got a bunch of these:
addScript(roofPathMrtu.js);
addScript(roofPathTrtu.js);
addScript(lowerPathMrtu.js);
etc...
Which I then need to check if they were successfully loaded or not, so I call:
UrlExists('roofPathMrtu.js');
The problem is that this UrlExists function is not working, and I think it's because it is running before all the addScript functions are done.
How can I have my UrlExists function run only after all the addScript functions are done? I was going to use the callback parameter of the addScript function on the last one, but I don't think that is gonna work.
A way that I have been doing this is not to use the javascript method of setimeout(), but using the jquery feature when. IF not, then I would use a Que. The syntax is
$.when(function()).then(fucntion2());
or
$.when(function1()).done(function2());
You could overlap these if you wanted to, but it is not best when considering both elegant and efficiency in code. Using the que would probably be the next step, using $.when will not accomplish what you want.
http://api.jquery.com/jQuery.when/
Your addScript() function is inserting the tag into the dom and returns immediately. At that point, the browser still needs to fetch the javascript file specified in the src attribute. I suppose that UrlExists() is being called after the execution of the addScript() functions but before the browser has a chance to fetch the javascript files.
use a $.Deferred object to "listen" to the various done events. You might want to combine a few $.Deferred object and use the $.when function to listen for multiple resolved promises
http://thiswildorchid.com/jquery-progress-and-promises check out this link it might help. But it sounds like you might need this. It helps a lot with async functions and you should see if it is a good fit for you.
What you want to do is define an onload function on the script element. It's not hard, but the implementation starts to look ugly. For the particular problem you're dealing with, I would recommend you look at Require JS.

Pass function to jQuery .ready() function

I am currently making use of Simon Willson's addLoadEvent function to add functions that I want to run after the load event. I ran into a problem wherein the the function I passed to the addLoadEvent function referenced a div that had not yet been loaded by the DOM and so my action (showing the div) did not do anything. When I changed to using the jQuery $(document).ready function, the div has been loaded by the DOM and I can execute actions with it (make it show up).
So, a couple questions. Why is my function being executed before the DOM has completed loaded using the above function? Is there a way to delay it? The other alternative that I can think of is passing in a function to a jquery equivalent:
function jqueryAddReadyEvent(myFunc)
{
$(document).ready(function()
{
//execute already existing functions
//add a new function to the ready event
myFunc();
}
}
When I try the above code, I get a javascript error "myFunc is not a function". Is there a way to generically pass in a function to the jquery ready function and have it execute? Equivalent to the following:
$(document).ready(function()
{
funcA();
}
$(document).ready(function()
{
funcB();
}
...//more of the same
Replaced with the following:
jQueryAddReadyEvent(funcA);
jQueryAddReadyEvent(funcB);
You can just do:
$(document).ready(myFunc);
to attach functions to the DOM ready event. Here's the fiddle: http://jsfiddle.net/padtE/
If you will require many functions to be added then I suggest you do the following:
Create an array that will old all the functions you want to call.
Add functions to that array as you please.
In the .ready(function() { ... }) call every function in that array.
You're set.
It looks correct to me. Most likely you are calling it with something not a function.
Btw you can shorten this to:
var jqueryAddReadyEvent = $(document).ready
or just use $(document).ready() directly for the same effect, as it specifically does what you want to do, run functions after the load, and is actually shorter.
$(document).ready(funcA);
$(document).ready(funcB);
function jqueryAddReadyEvent(myFunc) {
$(myFunc);
}
jqueryAddReadyEvent(function() {
alert('hello world');
});
Demo: http://jsfiddle.net/AlienWebguy/UzMLE/

send $.post() one at a time ("adding a pause" but really: toggling a 'transmit' flag)

in jQuery, I iterate over an xml list of areas and do a POST request to get detailed information about each area. Because sending thousands of requests at once is debilitating for the client and server, I would like to set a flag so that I wait for a request to finish before sending the subsequent [next] request.
if the xml looks like this:
<area>5717</area>
<area>5287</area>
<area>5376</area>
then the xml parsing kinda looks like:
$(xml).find("area").each( function() {
doPost();
}
and the doPost() function looks like
doPost : function () {
$.post( ... )
}
Basically, I would like to add a toggling "wait" but I'm not sure how to achieve this. Is there a way I can keep the essential ".each" iteration or is another type of loop better for this?
Thanks in advance.
A general algorithm off the top of my head:
You could put the whole list into an array. Take the first item of the array and post it. In the success handler of your post you could recursively call the function with the next index int the list.
I wouldn't use async: false because it would then be a blocking operation, which I assume the OP doesn't want.
You can use:
$.ajaxSetup({async:false});
at the top of your script to make your AJAX calls synchronous.
Alternately, you can replace $.post() with $.ajax() and set the async flag to false.
can you do a setTimeout ? that will allow for the function to still process asynchronous and allow for you to wait for some time in there too.
http://www.w3schools.com/js/js_timing.asp
setTimeout(function() {}, 5000)
You can refactor your doPost() function to take the <area> element to process as an argument, and chain into the next element from your success callback. Something like:
(function doPost($area) {
if ($area.length > 0) {
$.post({
// your options,
success: function() {
// your success handling...
doPost($area.next("area"));
}
});
}
})($(xml).find("area").first());
EDIT: Maybe the code above was a little too compact indeed.
Basically, the aim is to refactor your function so that it takes a jQuery object containing the next <area> element to process, or nothing if processing should stop:
function doPost($area) {
if ($area.length > 0) {
// Perform POST request and call ourselves from success callback
// with next <area> element (or nothing if there's no such element).
}
}
Then call this function with the first <area> element to process:
doPost($(xml).find("area").first());
The first code fragment in my answer does both at the same time. Functions are first-class objects in Javascript, and you can call a function you've just defined by enclosing its definition with parenthesis and providing the usual argument list, also surrounded by parenthesis.

jquery/javascript - running two functions from an onComplete property

I'm using a plugin which has a property "onComplete".
So I set something like this "onComplete: completeHandler"
And it runs the function defined in:
function completeHandler()
I just need an additional one line of code that I need to run, is there a way to say to run two functions? Or is my best way to write another function called "alternateCompleteHandler" and at the end of that function call completeHandler()?
This is what you're looking for:
onComplete: function(){
function1();
function2();
}
If you want two functions to be run simultaneously, Use this:
setTimeout(function1,1);
setTimeout(function2,1);
If you want them to run after each other, do this:
onComplete: function() {completeHandler();alternateCompleteHandler();}
its called anonymous function.
I would say the most flexible way is to create a new function. I think there are better options for naming it, though :)

Categories