Passing a function as argument of another function to nested function - javascript

Little confusing. From within function evenCard I'd like to call function autoFlip and pass it function evenBack as an argument. Then to complicate things further, autoFlip needs to pass the argument to another function nested within it and then call function evenBack. Is this possible? Thanks!
function evenCard() {
autoFlip_toggle = true;
autoFlip(evenBack);
}
function autoFlip(back) {
// do other stuff
$(window).scroll(function() {
if (autoFlip_toggle == true) {
// Call evenBack somehow?
}
});
}
function evenBack() {
// Does stuff
}

Call back(); within autoFlip.
function autoFlip(back) {
// do other stuff
$(window).scroll(function() {
if (autoFlip_toggle == true) {
back();
}
});
}

To call evenBack from the scroll function just write evenBack();

Related

How to reuse conditional check for each function?

I have many functions example like this
function update() {
if (isAdminUser()) {
return false;
}
...
}
function get() {
if (isAdminUser()) {
return false;
}
...
}
...
is there any possible way to have the conditional statement
if (isAdminUser()) {
return false;
})
written once and run by itself at the beginning of each function. I'm using javascript
You could use a higher order function to encapsulate the logic needed to run before a specific function is run. Higher order functions take functions as parameters, therefore a possible solution to your problem could look like this:
function withIsAdminUser(callback) {
return function() {
if (isAdminUser()) {
return false;
}
return callback();
}
}
function getRaw() {
// Do something here, this whole function could also be inlined
}
const get = withIsAdminUser(getRaw);
If you use TypeScript try decorators.
Docs: https://www.typescriptlang.org/docs/handbook/decorators.html#decorators
maybe you can define a function that can accept another function as an argument and returns false if that function (i.e isAdminUser in your code snippet) returns true
const checkUser = func => func() && false
then the function can be used like:
function update() {
if (checkUser(isAdminUser)) {
// update() logic will only run if user is not admin
}
}
function get() {
if (checkUser(isAdminUser)) {
// get() logic will only run if user is not admin
}
}

passing multiple callback in a function

funcOne(cb) {
//some async actions
cb(resp) //pass resp to callback function
}
fucntionTwo(resp) { console.log(resp) }
fucntionThree(resp) { console.log(resp) }
funcOne(funcTwo)
funcOne(funcThree)
function one will run twice with above case, how can I make funcOne run once but trigger funcTwo and funcThree? I need to pass the resp from funcOne and execute funcTwo and funcThree Means passing multiple callback in funcOne.
I know I can pass multiple args but is there any other way to do that?
You could use the rest parameter syntax and then use a forEach and apply the functions. Something like
function funcOne(...cb) {
console.log("one");
cb.forEach(s => s.apply());
}
function funcTwo() {
console.log("two");
}
function funcThree() {
console.log("three");
}
funcOne(funcTwo, funcThree);
and you can call funcOne with any number of function parameters.
Simply pass multiple arguments as callback functions
function funcOne(cb1, cb2) {
cb1();
cb2();
}
if number of callbacks are going to be dynamic then iterate arguments
function funcOne() {
Array.from( arguments ).forEach( s => typeof s == "function" && s() );
}
and invoke it as
funcOne( function(){ console.log(1) }, function(){ console.log(2) }, function(){ console.log(3) } )
You can pass the two callback into your functionOne:
funcOne(cb1, cb2) {
cb1();
cb2();
}
funcOne(funcTwo, funcThree);
It's so easy:
function One(arg) {
Two(arg);
Three(arg);
}
Pass two functions as arguments
funcOne(a, b) {
a(); b();
}
funcOne(funcTwo, funcThree)
If the scope of the functions is the way you have mentioned then you do not need to even pass them as arguments. Just directly call them.
function funcOne() {
//some async actions
var resp = "Some response";
fucntionTwo(resp);
fucntionTwo(resp);
}
funcOne();
function fucntionTwo(resp) { console.log(resp) }
function fucntionThree(resp) { console.log(resp) }
You can make use of arguments keyword.
Demo Example
function test()
{ for(var i=0; i< arguments.length; i++)
arguments[i]();
}
test(fun1 , fun2)
You can follow this code, I hope your problem will be solved
function funcOne(fucntionTwo, fucntionThree) {
fucntionTwo(resp)
fucntionThree(resp)
}
funcOne(function (resp) {
console.log(resp)
}, function (resp) {
console.log(resp)
})

jQuery with Callback and Complete

So I want to use a callback function within .fadeOut() after it complete's the animation. I can do this successfully using the following, no problem. Works just like I want (The HTML and CSS are just a single black square div)
function fadeOutThing(speed, callback) {
$('div').parent().fadeOut(speed, function() {
if (typeof callback === "function") {
callback();
}
});
}
function OtherThing() {
console.log("hello");
}
fadeOutThing(5000, OtherThing);
What I really want is for that callback function have its own argument, which could be another callback function, like the following. The problem is that when I do this, the log will display before the animation is complete: Here's the fiddle
function fadeOutThing(speed, callback) {
$('div').parent().fadeOut(speed, function() {
if (typeof callback === "function") {
callback();
}
});
}
function OtherThing(stuff) {
console.log("hello" + stuff); //This displays too soon!
}
fadeOutThing(5000, OtherThing(' stuffsss'));
Why is this happening? What am I not understanding?
The issue is because you call OtherThing() immediately on load of the page. This means you're giving the result of the OtherThing() function as the callback parameter, not the reference to the function.
To do what you require you can provide an anonymous function to the callback which wraps your OtherThing() call:
fadeOutThing(5000, function() {
OtherThing(' stuffsss'));
});
Bind the argument instead of calling the function as follows:
fadeOutThing(5000, OtherThing.bind(this,' stuffsss'));
Your are using/calling function in attribute so instead of function declaration you send its return in this case is no return so:
fadeOutThing(5000, OtherThing(' stuffsss'));
equals
fadeOutThing(5000, notDeclaredNothing); //undefined variable
To send function declaration and set paramaters you could do for example third paramater:
function fadeOutThing(speed, callback,attrs) {
$('div').parent().fadeOut(speed, function() {
if (typeof callback === "function") {
callback(attrs); //use with attributes
}
});
}
usage:
fadeOutThing(5000, OtherThing,'stuffsss');
Or second option is to use bind - bind creates new function with given this and given attributes:
fadeOutThing(5000, OtherThing.bind(this,'stuffsss'));
This in global scope is window object.

Make a function that can perform multiple callback with one parameter

I'm working on a big project and I simplified what it matters here. This is the code:
a = new Thing(/*sayHi + sayHey*/);
function sayHi() {
alert("hi");
}
function sayHey() {
alert("hey");
}
function Thing (callback) {
callback();
}
I'd like to, with just the callback parameter, call both the sayHi() and the sayHey() function, at the order I put them. Is it possible? How would I do it? Thank you.
Pass an anonymous function that calls both of them sequentially:
a = new Thing(function() {
sayHi();
sayHey();
});
function sayHi() {
alert("hi");
}
function sayHey() {
alert("hey");
}
function Thing (callback) {
callback();
}
Alternatively to #Barnar's answer, create and pass a regular named function. If the callback logic gets heavier, you might want that anyway.
function hiHeyCallback() {
sayHi();
sayHey();
}
a = new Thing(hiHeyCallback);

Same event callback function on more elements - assigned by cycle

I made code like this, to easier connecting callbacks on events:
dojo.ready(function() {
for(var action in page.actions) {
for(var key in page.actions[action]) {
(function() {
dojo.query(key).connect(action, function(evt) {
if(page.actions[action][key]() == false)
dojo.stopEvent(evt);
});
})();
}
}
});
page = {
actions :
{
onclick :
{
"#page-action-one" : function()
{
alert("Action 1");
return false;
},
"#page-action-two" : function()
{
alert("Action 2");
return false;
}
}
}
};
But click on "#page-action-one" an "#page-action-two" make the same alert("Action 2"). I tried to use cloer, but without effect. I now, I can make it different way, but I would like to now, why is this happening.
You're trying to fix the closure issue by wrapping your event handler assignment in an anonymous function. But the key to that trick is that you have to pass in the looping variable (or variables) as an argument to the anonymous function - otherwise the anonymous function wrapper does nothing. Try:
dojo.ready(function() {
for(var action in page.actions) {
for(var key in page.actions[action]) {
(function(action, key) {
dojo.query(key).connect(action, function(evt) {
if(page.actions[action][key]() == false)
dojo.stopEvent(evt);
});
})(action, key);
}
}
});
This "fixes" the value of action and key at the time the anonymous function is called, so within the anonymous function those variable names only apply to the passed arguments, not to the named variables in the outer scope, which will update on the next loop iteration.

Categories