I need to write a function:
function doTestConnCall(param1, param2, callbackfun)
param1 & param2 are parameters which I have used inside the function.
The 3rd parameter - callbackfun is a function which to be called after finishing doTestConnCall
How to achieve this?
Is it possible to pass 2 callbacks inside a single method. Say doTestConnCall(param1,callback1,callback2)
Think I am missing some basics. Could any one lead me
You can do something like this:
callbackfun(argument1, argument2);
or:
callbackfun.apply(this, [ argument1, argument2 ]);
or:
callbackfun.call(this, argument1, argument2);
The same can be done with multiple callbacks. For example:
callback1.call(this);
callback2.call(this);
See: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply
And: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/call
Functions in JS are top level constructs. That means function hello() {} is the same as var hello = function() {};. So if you want to pass hello to the function above, you can just call doTestConnCall(param1, param2, hello) after you have defined hello() using either method above.
This is how you achieve it.
It is possible to pass what ever you want to as a method parameter.
function doTestConnCall(param1, param2, callbackfun){
DO YOUR LOGIC
callbackfun() // CALL YOUR CALLBACK
}
Call any callback whenever appropriate in the function you are writing--in the case you described, after it completes its core work.
Yes, of course. Call them one after another.
function multipleCallbacks(arg, arg, callback1, callback2) {
// Do some stuff
// Do error checking in the real world if you need to be tolerant
callback1();
callback2();
}
Related
I have an ecma6/es2015 class with a getter defined like so:
get foo() { return this._foo; }
What I'd like to be able to do is pass that function as a parameter. Making a call like so:
someFunction(myClass.foo);
will simply invoke the function. Is there a clean way I can pass the method without invoking it and then invoke in the pass I'm passing it into?
I assume you'll have to wrap it into an anonymous function to keep it from getting executed:
someFunction(() => myClass.foo);
Or, you can get the getter function itself, but it is less readable than the above:
someFunction(Object.getOwnPropertyDescriptor(myClass, 'foo').get);
Not sure I understood you do you mean a way to define the function and pass it later to another one (as a function) to be invoked later?
something like this?
var myFunc = function() {
console.log('func');
document.getElementById('result').innerHTML='func';
}
console.log( 'start');
document.getElementById('result').innerHTML='start';
setTimeout( myFunc, 3000 );
console.log( 'end');
document.getElementById('result').innerHTML='end';
<h1 id='result'>default</h1>
Is it possible to write this without the surrounding "wrapper" anonymous function() ?
So, basicly turn runner(function(){ myfunction('hello world') }, 'Works!!!') into this runner(myfunction('hello world'), 'Works!!!')
JS
function runner(func, something)
{
alert(something);
func();
}
function myfunction(value)
{
alert("I should execute last!");
}
HTML
<button onclick="javascript: runner(function(){ myfunction('hello world') }, 'Works!!!')">Hit me</button>
JS FIDDLE http://jsfiddle.net/pST95/
It turns out that you can do that after all :-) You can use Function.prototype.bind to create a new function object, with the first parameter as the current context and rest of the arguments as the arguments to the actual function.
function runner(func, something) {
console.log(something);
func();
}
function myfunction(value) {
console.log(value);
console.log("I should execute last!");
}
runner(myfunction.bind(this, 'hello world'), 'Works!!!')
Output
Works!!!
hello world
I should execute last!
Is it possible to write this without the surrounding "wrapper" anonymous function()?
To have pre-set parameters you'll need to use a wrapper function one way or another. It's convenient to not need to declare it inline, but all solutions will still require that a wrapper function is used.
The ability to pre-set parameters to a function before it's executed is called "Partial Application". Basically the concept is that you call a function to generate a new function. The new function will call the original function with the correct parameters.
Vanilla JavaScript
Function.prototype.bind allows for additional arguments to be passed after the context which will then be used when the function is eventually called:
runner(myfunction.bind(window, 'hello world'), 'Works!!!');
Of course, IE8 and below don't support this function, so you'll need to use the polyfill to enable this behavior.
jQuery
$.proxy is the cross-browser compatible version in the jQuery library:
runner($.proxy(myfunction, window, 'hello world'), 'Works!!!');
Underscore
_.bind is the cross-browser compatible version in the Underscorejs library:
runner(_.bind(myfunction, window, 'hello world'), 'Works!!!');
however if you want to avoid binding the context when generating the wrapper, underscore also provides a true partial application function.
_.partial will bind the arguments only and allow the context to be determined when the function is executed:
runner(_.partial(myfunction, 'hello world'), 'Works!!!');
What you also can do is use apply or call, so that:
<button onclick="javascript: runner(myfunction,'hello world', 'Works!!!')">Hit me</button>
function runner(func, args, something)
{
alert(something);
func.call(this, args);
}
function myfunction(value)
{
alert("I should execute last!");
}
Your runner function expects a function that takes no arguments because it runs it like this:
func();
So you can't really pass myfunction to it like this:
runner(myfunction, 'Works!!!')
Because you don't have a way to give myfunction an argument (technically it does actually work because your myfunction doesn't use the argument anyway). But if you try this:
runner(myfunction('hello world'), 'Works!!!')
Then all you are doing is calling myfunction directly and sending the returned value (in this case undefined) as an argument to runner and if you look at the console, you should see an error: TypeError: undefined is not a function
So no, you need the wrapper from your original call or you can use Function.prototype.bind as thefortheye suggested.
I need to feed a pipe() handler function a bunch of function names so it can execute them in order, waiting for completion of each as it goes. This is great when those functions don't need parameters passing, but when parameters are needed I can't figure out how to pass them without the function going ahead and invoking itself (caused by the brackets).
For example, this is what I typically pass:
pipeHandler([function1, function2]);
It'll then invoke function1() and function2() before the promise is completed.
Where it gets difficult is when I want to do something like thiss:
pipeHandler([function1('value'), function2]);
That causes function1() to invoke immediately, completely bypassing the promise mechanism.
In case it helps, this is the handler function:
function pipeHandler(requiredFunctions) {
//Execute first required function
var executeFunctions = requiredFunctions[0]();
//Execute each subsequent required function using pipe()
for ( var index = 1; index < requiredFunctions.length; index++ ) {
executeFunctions = executeFunctions.pipe(requiredFunctions[index]);
}
//Execute allDone() using pipe()
executeFunctions = executeFunctions.pipe(allDone);
}
Hope somebody has an idea!
Why not
pipeHandler([function() { function1('value'); }, function2]);
?
This is where anonymous functions shine. If you spend some time working in Javascript, you'll probably encounter the same problem when using setTimeOut at some point.
This can be done concisely using bind. Syntax:
pipeHandler([function1.bind(scope, 'value')]);
Bind returns a partial function application, which is a new function in scope scope, with the fixed first parameter 'value'. It'll work with any number of arguments.
You can use an anonymous function, which can invoke the function1
pipeHandler([function () {;
function1('value')
}, function2]);
if you wanna pass parameters without invoking function you may do it like so :
function add (a, b) {
return a + b;
}
// Outputs: 3
console.log(add(1, 2));
// Outputs: function
console.log(add.bind(this, 1, 2));
and this will return a function
function () { [native code] }
if you wanna invoke it
// this will return 3
console.log(add.bind(this, 1, 2)());
What you're probably looking for is called 'Partial application.'
Depending on which browsers you need to support you may be able to simply use bind.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Partial_Functions
As far as I can tell from reading the question, there is no asynchronicity, just a regular single-threaded sequence of function calls, with the possibility of passing parameters at each call.
If so then you want to use jQuery.Callbacks. Your scenario is precisely what jQuery.Callbacks are for. The documentation says :
The jQuery.Callbacks() function, introduced in version 1.7, returns a
multi-purpose object that provides a powerful way to manage callback
lists. It supports adding, removing, firing, and disabling callbacks.
Having read the documentation for jQuery.Callbacks, it's probably still not obvious how to pass parameters to functions in the list.
The simplest option is to fire the list with an object that can be used by the functions in the list :
function myFunction1(obj) {
console.log(obj.myProperty1);
}
function myFunction2(obj) {
console.log([obj.myProperty1, obj.myProperty2].join());
}
var callbacks = $.Callbacks();
callbacks.add(myFunction1);
callbacks.add(myFunction2);
callbacks.fire({
myProperty1: 'X',
myProperty2: 'Y'
});
A more sophiisicated approach allows you :
to specify parameter(s) for each function as it is added to the list, and
to specify a context for all functions in the list
thus giving you two mechanisms for passing data to the functions and the freedom to specify that data in either a .add() statement or a .fire() statement, or both.
For this, you need the following utility function :
function makeClosure(fn) {
var args = Array.prototype.slice.call(arguments, 1);//seriously clever line - thank you John Resig
return function (context) {
fn.apply(context, args);
}
}
which can be used as follows :
function f1() {
console.log(this.myProperty));
}
function f2(value1, value2) {
console.log(value1 + ', ' + value2);
}
function f3(value1, value2) {
//note the use of `this` as a reference to the context.
console.log(value1 + ', ' + value2 + ', ' + this.myProperty);
}
var callbacks = $.Callbacks();
callbacks.add(makeClosure(f1, 'A1'));
callbacks.add(makeClosure(f2, 'B1', 'B2'));
callbacks.add(makeClosure(f3, 'C1', 'C2'));
callbacks.fire({
myProperty: 'Z'
});
DEMO
jQuery's $.proxy(function, context, value) is particularly helpful in this case since it:
Takes a function and returns a new one that will always have a particular context.
Therefore, not only you can change the context of the function being invoked (you can provide an object instead of this), but you can also pass as many arguments/parameters values as the function receives without invoking it directly:
function fun_w_param(v) {console.info("I'm #1, here's my value: " + v)}
function fun_no_param() {console.info("I'm #2")}
function pipeHandler(f1, f2) {
f2();
console.warn("Handling function1 with a second delay");
setTimeout(function(){f1()}, 1000);
}
// add your value below as a proxy's argument
pipeHandler(
$.proxy(fun_w_param, this, '!!!PROXY!!!'),
fun_no_param
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Running the above will delay "function1" execution and it will display the value that you provide into the proxy's parameter.
Using arrow methods you can simply do this
pipeHandler([() => function1('value'), function2]
I want to write my own function in JavaScript which takes a callback method as a parameter and executes it after the completion, I don't know how to invoke a method in my method which is passed as an argument. Like Reflection.
example code
function myfunction(param1, callbackfunction)
{
//do processing here
//how to invoke callbackfunction at this point?
}
//this is the function call to myfunction
myfunction("hello", function(){
//call back method implementation here
});
You can just call it as a normal function:
function myfunction(param1, callbackfunction)
{
//do processing here
callbackfunction();
}
The only extra thing is to mention context. If you want to be able to use the this keyword within your callback, you'll have to assign it. This is frequently desirable behaviour. For instance:
function myfunction(param1, callbackfunction)
{
//do processing here
callbackfunction.call(param1);
}
In the callback, you can now access param1 as this. See Function.call.
I too came into same scenario where I have to call the function sent as parameter to another function.
I Tried
mainfunction('callThisFunction');
First Approach
function mainFuntion(functionName)
{
functionName();
}
But ends up in errors. So I tried
Second Approach
functionName.call().
Still no use. So I tried
Third Approach
this[functionName]();
which worked like a champ. So This is to just add one more way of calling. May be there may be problem with my First and Second approaches, but instead googling more and spending time I went for Third Approach.
function myfunction(param1, callbackfunction)
{
//do processing here
callbackfunction(); // or if you want scoped call, callbackfunction.call(scope)
}
object[functionName]();
object: refers to the name of the object.
functionName: is a variable whose value we will use to call a function.
by putting the variable used to refer to the function name inside the [] and the () outside the bracket we can dynamically call the object's function using the variable. Dot notation does not work because it thinks that 'functionName' is the actual name of the function and not the value that 'functionName' holds. This drove me crazy for a little bit, until I came across this site. I am glad stackoverflow.com exists <3
All the examples here seem to show how to declare it, but not how to use it. I think that's also why #Kiran had so many issues.
The trick is to declare the function which uses a callback:
function doThisFirst(someParameter, myCallbackFunction) {
// Do stuff first
alert('Doing stuff...');
// Now call the function passed in
myCallbackFunction(someParameter);
}
The someParameter bit can be omitted if not required.
You can then use the callback as follows:
doThisFirst(1, myOtherFunction1);
doThisFirst(2, myOtherFunction2);
function myOtherFunction1(inputParam) {
alert('myOtherFunction1: ' + inputParam);
}
function myOtherFunction2(inputParam) {
alert('myOtherFunction2: ' + inputParam);
}
Note how the callback function is passed in and declared without quotes or brackets.
If you use doThisFirst(1, 'myOtherFunction1'); it will fail.
If you use doThisFirst(1, myOtherFunction3()); (I know there's no parameter input in this case) then it will call myOtherFunction3 first so you get unintended side effects.
Another way is to declare your function as anonymous function and save it in a variable:
var aFunction = function () {
};
After that you can pass aFunction as argument myfunction and call it normally.
function myfunction(callbackfunction) {
callbackfunction();
}
myfunction(aFunction);
However, as other answers have pointed out, is not necessary, since you can directly use the function name. I will keep the answer as is, because of the discussion that follows in the comments.
I will do something like this
var callbackfunction = function(param1, param2){
console.log(param1 + ' ' + param2)
}
myfunction = function(_function, _params){
_function(_params['firstParam'], _params['secondParam']);
}
Into the main code block, It is possible pass parameters
myfunction(callbackfunction, {firstParam: 'hello', secondParam: 'good bye'});
callbackfunction = () => {}
callbackfunction2(){
}
function myfunction1(callbackfunction) {
callbackfunction();
}
//Exe
myfunction1(callbackfunction);
myfunction1(callbackfunction2.bind(this));
Super basic implementation for my use case based on some excellent answers and resources above:
/** Returns the name of type member in a type-safe manner. **(UNTESTED)** e.g.:
*
* ```typescript
* nameof<Apple>(apple => apple.colour); // Returns 'colour'
* nameof<Apple>(x => x.colour); // Returns 'colour'
* ```
*/
export function nameof<T>(func?: (obj: T) => any): string {
const lambda = ' => ';
const funcStr = func.toString();
const indexOfLambda = funcStr.indexOf(lambda);
const member = funcStr.replace(funcStr.substring(0, indexOfLambda) + '.', '').replace(funcStr.substring(0, indexOfLambda) + lambda, '');
return member;
}
How do I make the myFunction visibile for the in-line function in .ready() event?
$(document).ready(function() {
...stuffs...
myFunction(par1, par2, anotherFucntion_callback);
}
);
function anotherFunction_callback(data) {
..stuffs..
}
I didn't quite catch your question. Do you mean that you want to pass "myFunction_callback(data)" as the last argument in your:
myFunction(par1, par2, anotherFunction_callback);
, including that "data" parameter?
In that case the solution is pretty standard, write this before that one:
var temp = function() { anotherFunction_callback(data) };
an alternative syntax is:
function temp() { myFunction_callback(data) };
// even though this looks just like a free function,
// you still define it inside the ready(function())
// that's why I call it "alternative". They are equivalent.
In general, if you want to pass a function with 1 or more arguments to another function, you use that format. Here, we basically create a new no-argument function that calls another. The new function has access to the "data" variable. It's called "closure", you may want to read more on that.
Of course, if the callback require no argument, you can just use the original function name.
I hope this helps.
ps: You can even inline the function declaration, making it anonymous, like so:
myFunction(par1, par2, function() { myFunction_callback(data) });
Notice that the
$(document).ready(function() {});
looks pretty much just like that.
You use the actual name of the function, i.e. myFunction_callback instead of myFunction or anotherFucntion_callback.