javascript - detect end of chained functions? - javascript

Today I'm working on a pet project using chained function calls, and I'm curious how I might detect when the last function in the chain is executed. For example:
func1('initial data').func2().func3().func4();
And after func2-4 have finished working on 'initial data' I'd like to detect when func4 is done. Since func4() isn't always the last function in the chain, aka it could end at .func3() or .func5() for example, or I could mix my function calls up depending on what I'm trying to do, I'm trying to think of a way to detect no more function calls are being done but I'm not getting very far.

You can't.
Besides, if they are not chained:
var v = func1('initial data');
v = v.func2();
v = v.func3();
v = v.func4();
What would you consider to be the last function? Every function is the last function in it's own chain, but if you finalise something after each step, that won't work.
Just make a function that you call last to finalise the process.

The traditional approach is to put whatever you want done after the final function on the next line:
func1('initial data').func2().func3().func4();
allFunctionsDone();
;)

You can write the sequencer, which will help you to do this for you. Instead of executing direct calls, shift the names of the functions and call them one by one. Something like this
executeSequence(func1('init_dat'),[
'func2',
'func3',
'func4'
]);

Related

In JavaScript, is there a universal approach to known when asynchronous actions are finished?

In my work, I frequently encounter following situation:
Situation A:
I need to make multiple ajax calls in one function to retrieve data from server. So I have to make callback functions and define a counter to determine whether all the calls get done.
For example , in each of the sub-functions ( with ajax calls), at the end of the done, I would callback to check the counter's value.
ajax.done(funciton(jsResponse){
.......
base.ajaxLoaded++;
base.dataLoaded();
});
then in base function, I check the value:
dataLoaded: function()
{
var _this = this;
if (_this.ajaxLoaded == 4)
{
// all loaded
_self.render();
_this.afterInit();
}
}
Situation B:
There is a modal pop up triggered by the completion of an animation. So, I have following choices:
1) make a setTimeout function with a timer ( estimated the length of animation)
something like:
setTimeout(function(){
window.MYAPP.triggerMymodal();
},1000);
2) set up a interval function to check repeatedly whether a flag's value has changed and I embedded this flag into the animation finish function, to set it true or false.
if this flag true then make my next move and kills this interval.
3) change animation div attributes and check it use interval function.
Situation C:
Use window.print() function to print something and then need detect when it's finish. This has been asked by myself in this:
how to detect window.print() finish
My Question:
In JavaScript, is there a certain kind of method or Technic to deal with those functions which have unknown execution time? or this is just a case by case thing based on what technology you use?
Yes, the modern approach to dealing with this is called Promises. Various libraries implement the concept, which is basically that you can chain together groups of things that need to happen, either is parallel or serial, and then define success and failure outcomes for each of them.
It takes a bit of time to get your head around it but once you do the code is much more straightforward.

Execute just part of a method in JavaScript

I have a method that could potentially do both parts of the greater task at hand. Basically I have two buttons one button uses the entire method and returns a result at the bottom of the method. Now, my question is about the second button. The second button needs to do everything in that same method but only from line x of said method. Instead of writing a second method that repeats the same exact code from line x down of said method is there a way to jump over bits of code and only execute portions of a method in javascript? Or perhaps I am thinking about this all wrong?
Do two separate methods like this:
function a(){
//do first half of function
b();
}
function b(){
//do second half of function
}
2 ways,
split out the chunk that gets used twice into a separate method, and call from either within the first method, or from the other context directly.
add another argument to the method that expects a boolean value. The function then skips over the unneeded bits based on that value passed in. It can then be called differently from different contexts.
you can call String(yourfunc) to get code, then dynamically create second function by cutting only further lines, you can get array of lines by splitting by ('\n') then join array elements from place you want to begin and evaluate new function, code:
function split(bigfunc,line){
for(var small = String(bigfunc).split('\n'), i=line,n='',l=small.length;++i<l;)
n+=small[i];
return eval('(function(args){'+n+')'};
}
where args in last line you need to replace with args from original function, eventually you can assume args will be the same, then replace line with:
return eval('('+small[0]+n+')') if you're putting { after arguments of function like me or put +'{'+ between small[0] and n if you're putting { in new line.
it'll return new function with only code after line.
Dude, look how many lines of code will you save...
To be serious - it's overkill. I'm using dynamic code manipulation like this to dynamically create webworkers only with parts of code from primary thread and crafting blobs and urls to them in fly to reduce loading time. But it's way more serious purpose than just making code shorter, but...
at least it'll be soooo pro xD

How to halt Javascript code without alert

Is, is there any function which does the exact same thing as alert except doesn't bring up an alert box? (a function which halts ALL executing JS code for a given amount of time, but doesn't bring up an alert message).
setTimeout doesn't work since it only halts the cod which is inside the setTimeout function.
a javascript function that will stop your code for some time is setTimeout(),
for more information on how to use this function please reffer to the following link : http://www.w3schools.com/jsref/met_win_settimeout.asp
You could split it into two functions and have the first initiate a time-out.
function func1(){
//do stuff
setTimeout('func2',2000);
}
function func2(){
//do some more
}
The function setTimeout will execute for later whatever function you pass to it. So it will not really pause the execution of your code, unless the code is split into parts and placed within calls of setTimeout. Maybe that is an approach.
Another approach could be to use delay function (http://api.jquery.com/delay/) along your jquery calls.
But in all cases the best is to find out what is causing this behaviour and fix it in code.
Have you tried using the DOM elements rather than JQuery to create the new node.
http://www.w3schools.com/jsref/met_node_appendchild.asp
var startTime = new Date().getTime();
while(new Date().getTime() < startTime + 1000) {}
This waits for 1000ms / 1 sec.
During that time, your browser is completely unresponsive and possibly doesn't render any stuff you may be waiting for, but hey, ... there you go ;)

jQuery plugin on multiple elements executes asynchronously

EDIT - Js fiddle link to script file - http://jsfiddle.net/r4uH3/
EDIT 2 RE ACCEPTED ANSWER Although question already closed, thought I would add some detail on why I accepted the answer below.
Also see this re why original code didn't work - How do I return the response from an asynchronous call? - it's points re AJAX are not literally related, but the explanation of asynchronicity is important to understand.
Fabrício Matté's answer works perfectly for me, although I adapted it slightly:
(function($){
// some pre-iteration stuff here
// iteration vars
var elementIndex = 0;
var collectionLength = this.size();
var ts = this;
// THIS IS THE KEY BIT AS PER ACCEPTED ANSWER
// RATHER THAN USING THE NORMAL "this.each"
(function initLoop(){
// check if got to last element
if (elementIndex < collectionLength){
// DO STUFF, WHATEVER, AS LONG AS YOU DON'T EXPECT
// ASYNCHRONOUS FUNCTIONS LIKE AJAX / TIMERS NOT TO, WELL, EXECUTE ASYNCHRONOUSLY UNLESS YOU HANDLE THEM PROPERLY!!
// AND FINALLY - GO TO NEXT ELEMENT IN COLLECTION
initLoop();
};
})());
})(jQuery);
The other thing that helped, although not exactly related, was using global and element-specific variables stored using jQuery(el).data(); rather than using window.VARIABLENAME or MyNamespace.VARIABLE_NAME. Eg:
// outside of iteration
jQuery(window).data("GLOBAL_STUFF", { /* add properties here and set them later*/ });
var globalData = jQuery(window).data("GLOBAL_STUFF");
// inside iteration
jQuery(currentElement).data("ELEMENT_DATA", { /* add properties here and set them later*/ });
var elementData = jQuery(window).data("ELEMENT_DATA");
// then set props like so (obviously get, similarly..)
globalData.someArrayOfSomething.push(something);
elementData.someBooleanValue = true;
Again, thanks to Fabrício.
I have written a jQuery plugin that, like most, can be executed on multiple (i.e. a collection of) elements.
in the this.each(function(i,el){ }); part of the function, I create a new instance of another object type (nothing to do with jQuery) and call its "Init" method.
I expect, with the .each loop, that it will loop to the next instance after the init method has been fully executed.
I am not using any async (AJAX / timers) anywhere.
I am using callbacks always on anything like "jQuery.fadeIn" or similar.
THE PROBLEM
The Init methods are called virtually in parallel. They do not complete their execution before the next one is called.
Can anybody advise of any known issues? Is there something I'm missing from the above "theory"?
Using jQuery 2.0.
Try replacing your for loop with:
var i = 0,
l = window.JRTE_INSTANCES.length;
(function initloop() {
if (i < l) window.JRTE_INSTANCES[i].Init(initloop);
i++;
}());
This will start the init loop by calling window.JRTE_INSTANCES[0].Init. The initloop passed as callback will execute again when the Init concludes, starting another Init with the next i and so forth until it has iterated over all instances.
Here's a more practical async demo using a very similar structure as the above: Fiddle

Javascript function as a parameter to another function?

I'm learning lots of javascript these days, and one of the things I'm not quite understanding is passing functions as parameters to other functions. I get the concept of doing such things, but I myself can't come up with any situations where this would be ideal.
My question is:
When do you want to have your javascript functions take another function as a parameter? Why not just assign a variable to that function's return value and pass that variable to the function like so:
// Why not do this
var foo = doStuff(params);
callerFunction(foo);
//instead of this
callerFunction(doStuff);
I'm confused as to why I would ever choose to do things as in my second example.
Why would you do this? What are some use cases?
Thanks!!
There are several use cases for this:
1. "Wrapper" functions.
Lets say you have a bunch of different bits of code. Before and after every bit of code, you want to do something else (eg: log, or try/catch exceptions).
You can write a "Wrapper" function to handle this. EG:
function putYourHeadInTheSand(otherFunc) {
try{
otherFunc();
} catch(e) { } // ignore the error
}
....
putYourHeadInTheSand(function(){
// do something here
});
putYourHeadInTheSand(function(){
// do something else
});
2. Callbacks.
Lets say you load some data somehow. Rather than locking up the system waiting for it to load, you can load it in the background, and do something with the result when it arrives.
Now how would you know when it arrives? You could use something like a signal or a mutex, which is hard to write and ugly, or you could just make a callback function. You can pass this callback to the Loader function, which can call it when it's done.
Every time you do an XmlHttpRequest, this is pretty much what's happening. Here's an example.
function loadStuff(callback) {
// Go off and make an XHR or a web worker or somehow generate some data
var data = ...;
callback(data);
}
loadStuff(function(data){
alert('Now we have the data');
});
3. Generators/Iterators
This is similar to callbacks, but instead of only calling the callback once, you might call it multiple times. Imagine your load data function doesn't just load one bit of data, maybe it loads 200.
This ends up being very similar to a for/foreach loop, except it's asynchronous. (You don't wait for the data, it calls you when it's ready).
function forEachData(callback) {
// generate some data in the background with an XHR or web worker
callback(data1);
// generate some more data in the background with an XHR or web worker
callback(data2);
//... etc
}
forEachData(function(data){
alert('Now we have the data'); // this will happen 2 times with different data each time
});
4. Lazy loading
Lets say your function does something with some text. BUT it only needs the text maybe one time out of 5, and the text might be very expensive to load.
So the code looks like this
var text = "dsakjlfdsafds"; // imagine we had to calculate lots of expensive things to get this.
var result = processingFunction(text);
The processing function only actually needs the text 20% of the time! We wasted all that effort loading it those extra times.
Instead of passing the text, you can pass a function which generates the text, like this:
var textLoader = function(){ return "dsakjlfdsafds"; }// imagine we had to calculate lots of expensive things to get this.
var result = processingFunction(textLoader);
You'd have to change your processingFunction to expect another function rather than the text, but that's really minor. What happens now is that the processingFunction will only call the textLoader the 20% of the time that it needs it. The other 80% of the time, it won't call the function, and you won't waste all that effort.
4a. Caching
If you've got lazy loading happening, then the textLoader function can privately store the result text in a variable once it gets it. The second time someone calls the textLoader, it can just return that variable and avoid the expensive calculation work.
The code that calls textLoader doesn't know or care that the data is cached, it's transparently just faster.
There are plenty more advanced things you can do by passing around functions, this is just scratching the surface, but hopefully it points you in the right direction :-)
One of the most common usages is as a callback. For example, take a function that runs a function against every item in an array and re-assigns the result to the array item. This requires that the function call the user's function for every item, which is impossible unless it has the function passed to it.
Here is the code for such a function:
function map(arr, func) {
for (var i = 0; i < arr.length; ++i) {
arr[i] = func(arr[i]);
}
}
An example of usage would be to multiply every item in an array by 2:
var numbers = [1, 2, 3, 4, 5];
map(numbers, function(v) {
return v * 2;
});
// numbers now contains 2, 4, 6, 8, 10
You would do this if callerFunction wants to call doStuff later, or if it wants to call it several times.
The typical example of this usage is a callback function, where you pass a callback to a function like jQuery.ajax, which will then call your callback when something finishes (such as an AJAX request)
EDIT: To answer your comment:
function callFiveTimes(func) {
for(var i = 0; i < 5; i++) {
func(i);
}
}
callFiveTimes(alert); //Alerts numbers 0 through 4
Passing a function as a parameter to another function is useful in a number of situations. The simplest is a function like setTimeout, which takes a function and a time and after that time has passed will execute that function. This is useful if you want to do something later. Obviously, if you called the function itself and passed the result in to the setTimeout function, it would have already happened and wouldn't happen later.
Another situation this is nice is when you want to do some sort of setup and teardown before and after executing some blocks of code. Recently I had a situation where I needed to destroy a jQuery UI accordion, do some stuff, and then recreate the accordion. The stuff I needed to do took a number of different forms, so I wrote a function called doWithoutAccordion(stuffToDo). I could pass in a function that got executed in between the teardown and the setup of the accordion.
Callbacks. Say you're doing something asynchronous, like an AJAX call.
doSomeAjaxCall(callbackFunc);
And in doSomeAjaxCall(), you store the callback to a variable, like var ajaxCallback Then when the server returns its result, you can call the callback function to process the result:
ajaxCallback();
This probably won't be of much practical use to you as a web programmer, but there is another class of uses for functions as first-class objects that hasn't come up yet. In most functional languages, like Scheme and Haskell, passing functions around as arguments is, along with recursion, the meat-and-potatoes of programming, rather than something with an occasional use. Higher-order functions (functions that operate on functions) like map and fold enable extremely powerful, expressive, and readable idioms that are not as readily available in imperative languages.
Map is a function that takes a list of data and a function and returns a list created by applying that function to each element of the list in turn. So if I wanted to update the positions of all the bouncing balls in my bouncing ball simulator, instead of
for(ball : ball_list) {
ball.update();
ball.display();
}
I would instead write (in Scheme)
(display (map update ball-list))
or in Python, which offers a few higher-order functions and a more familiar syntax,
display( map(update, ball-list) )
Fold takes a two-place function, a default value, and a list, and applies the function to the default and the first element, then to the result of that and the second element, and so on, finally returning the last value returned. So if my server is sending in batches of account transactions, instead of writing
for(transaction t : batch) {
account_balance += t;
}
I would write
(fold + (current-account-balance) batch))
These are just the simplest uses of the most common HOFs.
I will illustrate is with sort scenario.
Let's assume that you have an object to represent Employee of the company. Employee has multiple attributes - id, age, salary, work-experience etc.
Now, you want to sort a list of employees - in one case by employee id, in another case by salary and in yet another case by age.
Now the only thing that you wish to change is how to compare.
So, instead of having multiple sort methods, you can have a sort a method that takes a reference to function that can do the comparison.
Example code:
function compareByID(l, r) { return l.id - r.id; }
function compareByAge(l, r) { return l.age - r.age; }
function compareByEx(l, r) { return l.ex - r.ex; }
function sort(emps, cmpFn) {
//loop over emps
// assuming i and j are indices for comparision
if(cmpFn(emps[i], emps[j]) < 0) { swap(emps, i, j); }
}

Categories

Resources