I want to save all sections, made updates to questions with IDs for the just saved sections, then save the questions, and then if that is successful fire a function nextPage that redirects the page. I'm trying to confirm this is correct. It seems to act funny if I don't have the anonymous function wrapped around saveAllQuestions.
saveAllSections(function () {saveAllQuestions(nextPage)});
Update:
On the success of saveAllSections it does the following:
if (typeof(callback) == 'function')
callback();
On the success of saveAllQuestions it does the following:
if (questionValuesToSave.length>0) {
saveAllQuestionValues(questionValuesToSave, callback);
}
else {
// once its done hide AJAX saving modal
hideModal();
if (typeof(callback) == 'function')
callback();
}
On the success of saveAllQuestionValues (assuming there are some) it does the following:
if (typeof(callback) == 'function')
callback();
Yes that is a generally correct syntax for a callback, though its hard to know for sure without seeing more code.
The following code
saveAllSections(saveAllQuestions(nextPage));
would fail because saveAllQuestions(nextPage) is the syntax to execute a function, rather than define it. So it will execute that immediately and pass the result to saveAllSections, which will try to use it as the callback. Since this is likely not a function, and almost definitely not the function you want to pass you will get strange behavior, most likely an error.
Wrapping this in an anonymous function means that you're passing a function to saveAllSections, which does not execute until it is called by the outer function or as a callback.
UPDATE:
Looks like saveAllQuestions is also async based on your description, so executing it immediately will definitely not work correctly. The anonymous function wrapper is a completely acceptable solution if you need to pass a param.
If you didn't, you could just use
saveAllSections(saveAllQuestions)
The reason you need to wrap saveAllQuestions in an anonymous function is because otherwise saveAllQuestions gets executed right away, and its return value gets passed as the callback to saveAllSections.
If you wrap saveAllQuestions in an anonymous function, you prevent saveAllQuestions from executing right away.
In javascript, you can pass a function as an argument. This allows for simpler code and asynchronous callbacks. In your attempt, you don't pass a function in. You execute a function, so the result of saveAllQuestions(nextPage) is passed into the function, not the function saveAllQuestions.
Hopefully this example helps.
function add(a,b) {
return a+b;
}
function mul(a,b) {
return a*b;
}
function doMath(num1, num2, op) {
return op(num1, num2);
}
document.write( doMath(4,5, add) ); // 9
document.write( doMath(4,5, function (n1,n2) {return n1+n2;}) ); // 9
document.write( doMath(2,5, mul) ); // 10
document.write( doMath(2,5, function (n1,n2) {return n1*n2;}) ); // 10
document.write( doMath( doMath(1,3, add) , 4, mul) ); // 16
Related
Learning javascript and wanted to get more clarity regarding callbacks.
In the following code snippet,
function do_a( callback ){
// if callback exist execute it
callback && callback();
}
function do_b(){
console.log( 'do_b executed' );
}
//one way
do_a( function(){
do_b();
});
//other way
do_a(do_b);
Is there a difference between the two ways the do_a() is called. One passes a pointer to the do_b function, the other passes a function which executes the do_b function. All the examples i've seen use the first way. Is that more preferred style wise?
The first way just creates an extra anonymous function that calls the second function. This is useful if you want to perform actions before or after calling the callback, e.g.
do_a( function(){
console.log("I'm going to call the second function...");
do_b();
console.log("Second function is done.");
});
Otherwise, I can't see any point in this extra function and the second way is better.
you don't have to pass it as an argument. Directly call it.
function abc(){
a = "function abc";
console.log(a);
cde();
console.log(a);
}
function cde(){
a="function cde";
}
abc();
I am new to next(), done() etc. and am struggling with propagating parameters between serial executions/chaining of possibly otherwise asynchronous functions.
I want to force serial execution of 2 functions so they can be called with something like either:
f1('#{arg1a}', '#{arg1b}').done(
f2('#{arg2a}', '#{arg2b}')
);
OR something like:
f1('#{arg1a}', '#{arg1b}', '#{arg2a}', '#{arg2b}').done(f2);
Where the arg values passed in are gleaned from query parameters using JSF.
Note that:
arg2a and arg2b are in my case completely unrelated to arg1a and arg1b, and the invocation of f2 does NOT depend in any way on what happens in f1, other than it must execute strictly afterwards, even if f1 is otherwise usually asynchronous.
I am not defining on-the-fly anonymous functions or such inside done() here (yet), I want to be able to call a library-defined function with some known params.
In this example, the functions would be something like:
function f1(arg1a, arg1b) {
//do something with arg1a, arg1b
return $.Deferred().resolve();
}
function f2(arg2a, arg2b) {
// Do something with arg2a and arg2b AFTER f1 has fully run.
}
OR something like:
function f1(arg1a, arg1b, arg2a, arg2b) {
//do something with arg1a, arg1b
// Somehow ensure f1 is finished then execute f2(arg2a, arg2b)
}
function f2(arg2a, arg2b) {
// Do something with arg2a and arg2b AFTER f1 has fully run.
}
Just using callback chaining did not work for the situation I am tackling. See also: How link to and target/open a p:tab within an p:accordionPanel within a p:tab within a p:tabview
An acceptable answer MUST permit me to have a pre-defined function f2 with pre-defined parameters
You need to pass parameters to .resolve(), then use .then()
function f1(arg1a, arg1b) {
return $.Deferred(function(dfd) {
//do something with arg1a, arg1b
// you can alternatively call `.resolve()` without passing parameters
// when you are finished doing something with `arg1a`, `arg1b`,
// which should call chained `.then()` where `f2` is called
dfd.resolve(arg1a, arg1b)
}).promise();
}
function f2(arg2a, arg2b) {
// Do something with arg2a and arg2b AFTER f1 has fully run.
}
f1(arg1, arg2)
.then(function() {
// call `f2` here
f2('#{arg2a}', '#{arg2b}');
})
// handle errors
.catch(function(err) { // alternatively use `.fail()`
console.log(err)
});
jsfiddle https://jsfiddle.net/wuy8pj8d/
You've almost got it right except you've forgotten to wrap the code you want to execute in the future (when done is eventually called) inside a function:
f1('#{arg1a}', '#{arg1b}').done(function(){
f2('#{arg2a}', '#{arg2b}')
});
This also works with regular callbacks. For example, say you've defined f1 to accept a callback instead of a promise, you'd then do:
f1('#{arg1a}', '#{arg1b}',function(){
f2('#{arg2a}', '#{arg2b}')
});
Nothing special here. There's no separate syntax for forcing callbacks to accept custom arguments, just wrap it in another function.
This also works for variables thanks to closures:
var a='#{arg1a}', b='#{arg1b}';
var c='#{arg2a}', d='#{arg2b}';
f1(a,b).done(function(){
f2(c,d)
});
The variables c and d will be accessible within done().
I got the following code:
navigator.geolocation.getCurrentPosition(
successFunction
);
I was wondering why it is not required to use the '()' at the end of the succesFunction? Isn't it required to call a function with the '()' --> somefunction()
What's the logic behind it?
Because you're passing in the function reference, not the returned value of the function.
A function is a thing that can be invoked—where it runs code and returns a result. You invoke a function by using the parentheses. But, if you want to talk about the thing, if you want to pass the function around so that someone else can invoke it, you leave off the parentheses.
In this case, the getCurrentPosition() function is asking you to give it a function so that it can call it later on. So instead of invoking successFunction, you pass along a reference to it.
If you instead wrote:
navigator.geolocation.getCurrentPosition(
successFunction()
);
…then what would happen is successFunction() would be invoked—the code of the function would be run, and possibly return a value—and THEN you would invoke getCurrentPosition(), passing along as an argument whatever value successFunction returned.
In JavaScript you can pass functions as objects:
Try executing this example:
function myFunction() {
console.log('hello');
}
function anotherFunction(functionParameter) {
console.log('executing function passed as argument:');
functionParameter();
}
anotherFunction(myFunction);
This code will print:
"executing function passed as argument:"
"hello"
So i don't really understand the point of "callback".
Here is an example of callback:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name,myfunc){
alert("Hello");
myfunc;
}
sayHello("Max",saySeeYou());
Whats the point of passing in a function when you can just call the function? like this code does the exact same:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name){
alert("Hello");
saySeeYou();
}
sayHello("Max");
Whats the point of passing in a function when you can just call the function?
Usually, callbacks Javascript are used in Javascript for code that you want to run in the future. The simplest example is setTimeout: if you call the callback now then the code runs immedieately instead of after 500 ms.
//prints with a delay
console.log("Hello");
setTimeout(function(){
console.log("Bye");
}, 500);
//no delay this time
console.log("Hello");
console.log("Bye");
Of course, it would be really neat if we could write something along the lines of
//fake Javascript:
console.log("Hello");
wait(500);
console.log("Bye");
But sadly Javascript doesnt let you do that. Javascript is strictly single-threaded so the only way to code the wait function would be to pause the execution of any scripts in the page for 500 ms, which would "freeze" things in an unresponsive state. Because of this, operations that take a long time to complete, like timeouts or AJAX requests usually use callbacks to signal when they are done instead of blocking execution and then returning when done.
By the way, when passing callbacks you should only pass the function name. If you add the parenthesis you are instead calling the function and passing its return value instead:
//When you write
foo(10, mycallback());
//You are actually doing
var res = mycallback();
foo(10, res);
//which will run things in the wrong order
Your code is not correct as Felix Kling already pointed out. Besides this, passing a function instead of calling one directly allows you to insert different behavior, your code is more decoupled and flexible. Here an example:
function sayBye(){
alert("Bye!");
}
function saySeeYou(){
alert("See you!");
}
function sayHello(name,myfunc){
alert("Hello");
if (myfunc) {
myfunc();
}
}
sayHello("Max",saySeeYou);
// I'm inserting a different behavior. Now instead of displayng "See you!"
// will show "Bye!".
sayHello("Max",sayBye);
You are doing it wrong, you should do like bellow
Don't call the function just pass the function as callback
use this
sayHello("Max",saySeeYou); //here the second parameter is function
instead of
sayHello("Max",saySeeYou());//This will put the result of saySeeYou as second parameter
in say hello call the functiom
function sayHello(name,myfunc){
console.log("Hello");
myfunc();
}
I could explain my problem but it is likely easier to demonstrate it...
If you take a look at http://jsfiddle.net/XxT2B/ you'll see my issue. I am having trouble figuring out how to pass an action to a function. You'll see what I mean.
Please note that the action could be different based on what calls the function. The action may be an alert on time and something different the next.
Here is my code...
function abc(action)
{
//Do a bunch of stuff first and then do the action sent to this function
alert('This function is named "abc"');
//This is the part I do not know how to do.
//The action might be an alert or something totally different so I can't just pass text
//I need to know how to execute the action passed.
action;
}
abc('alert("I like pizza")');
You can pass a function as a parameter to another function.
function abc(action)
{
//Do a bunch of stuff first and then do the action sent to this function
alert('This function is named "abc"');
action();
}
abc(function(){
alert("I like pizza");
});
You can pass a function into abc(), but be sure to sanitize
function abc(action)
{
alert('This function is named "abc"');
if(typeof(action) == "function") { //sanitize
action();
}
}
abc('alert("I like pizza")'); //will execute without a problem
abc(50); //will not run, since 50 is not a function
The good way:
Pass it as a function:
function abc(action)
{
//Do a bunch of stuff first and then do the action sent to this function
alert('This function is named "abc"');
action();
}
abc(function(){alert("I like pizza")});
the bad way (if your actions need to be strings):
function abc(action)
{
//Do a bunch of stuff first and then do the action sent to this function
alert('This function is named "abc"');
eval(action);
}
abc('alert("I like pizza")');
The second way is not advised because eval causes issues. It can run arbitrary code that can cause unexpected side effects, prevents compiler optimizations, and leads to difficulty debugging (since it can literally do anything depending on what you pass it). More on why eval is bad here.
But it will run an arbitrary string as javascript code like you were asking.
You just need to instantiate a function:
abc(function() { alert("I like pizza"); });
edit and then to call it, you use the value of your parameter exactly as if it were a function name (because, well it is!):
action();
You can use the eval method:
function abc(action)
{
//Do a bunch of stuff first and then do the action sent to this function
alert('This function is named "abc"');
eval(action);
}
abc('alert("I like pizza")');
And that's that.
Don't know what JavaScript version supports this syntax but you also can try:
function abc(action) {
if (typeof(action) != 'function')
return;
action();
}
abc(() => console.log('A B C'));