How to re-bind() the same function in Javascript? - javascript

I am writing a wrapper that accepts a callback function to pass on to another function or execute directly. The problem is that another functions have bound parameters with callback parameter having a different argument number. Therefore initial binding would accept a string placeholder that needs to be replaced. But how?
function callback(){}
function asyncfunc1(a,b,callback,d){ callback();}
function asyncfunc2(a,b,c,callback){ callback();}
function asyncfunc3(callback,b,c,d){ callback();}
function wrap(cond,func,callback){
if (cond) {
// here I want to execute the passed function
// however instead of real callback, I have a placeholder bound
// so how do I bind it again to replace it with real callback?
func();
}
else callback();
}
wrap(cond,asyncfunc1.bind(null,param1,param2,'callback',param3),callback)
// this is what it's used for, is to create a flow of conditional callbacks
wrap(cond1,asyncfunc1.bind(null,param1,param2,'callback',param4),function(){
wrap(cond2,asyncfunc2.bind(null,param1,param2,param3,'callback'),function(){
wrap(cond3,asyncfunc3.bind(null,'callback',param2,param3,param4),callback
}
})

I am going to avoid bind and pass a function with arguments as an array.
function wrap(cond,fn_arr,callback){
if (cond) {
if (fn_arr instanceof Array){
var func=fn_arr.shift();
if (fn_arr.includes('callback')) {
fn_arr[fn_arr.indexOf('callback')] = callback;
}
func(...fn_arr)
} else fn_arr();
}
else callack();
}
Then with little array manipulation will do the replacement trick.
wrap(cond,[asyncfunc,param1,param2,'callback',param4],callback)

Related

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.

Cleaner callbacks in JavaScript

If I want to break a callback implementation out of a method's parameter footprint for cleaner code I can do (for example)
foo.bar(a, callback(), b);
function callback() {
stuff;
}
instead of
foo.bar(a, function() {
stuff;
}, b);
But what do I do if the method passes something into the callback like three.js's loader functions? (http://threejs.org/docs/#Reference/Loaders/OBJMTLLoader)
foo.bar(callback(object));
function callback(object) {
object.stuff();
}
doesn't seem to work.
Got it. The format should be:
foo.bar(callback);
function callback(object) {
object.stuff();
}
The 2 snippets you've posted are actually different - when you pass an anonymous function as an argument it isn't run immediately, but in the "foo.bar" function itself. However, when you pass it as "callback()", that function runs immediately (it is useful in some cases, for example: if the function returns another function). So, pass it without "()".
For example:
function a(){
alert(1);
}
function b(callback){
callback(); //run the callback function.
}
b(a);
And, if you want to see an example of the second option:
function a(){
return function() {
alert(1);
};
}
a()(); //Alert
b(a()); //Alert
b(a) //nothing happens

Call an javascript function and pass in callback function

I want to call a javascript function in Action script, something like this:
ExternalInterface.call('a_js_function', param1, another_js_function);
I want the javascript function a_js_function takes in two params, one is a string, another one is a callback function. So I can call the js function like this:
function a_js_function(testStr, callback) {
console.log(testStr);
callback(testStr);
}
function another_js_function(str) {
console.log(str);
}
What is the correct way to do this?
Problem solved, it turns out the second I passed in is a string, in javascript I have to turn string into function in order to call it.
call like this
try {
ExternalInterface.call('a_js_function', param1, another_js_function);
} catch(e:Error) {
trace(e)
}
and for more information see this
Since flash does not have any reference to the javascript function another_js_function you need to pass the function name as a string then access it using brackets on whichever namespace. I used global variables for simplicity but it can be any object/namespace
another_js_function = function(testStr) {
alert(testStr);
}
a_js_function = function(testStr, callback) {
console.log( this.window );
window[callback].call(this, testStr); // pass scope?
// OR
window[callback](testStr);
}
// Simulating call from Flash
a_js_function("howdy y'all", "another_js_function");
In Action: http://jsfiddle.net/3n1gm4/Np3bW/

How to properly pass two objects through two functions in jQuery

My series of methods are like so :
onUpdateAcrossDown ( findAcrossAndDownWords( across_index, down_index ) )
I want to reuse findAcrossAndDownWords, so I'd like it to return my two objects that I can pass into other methods if need be.
findAcrossAndDownWords: function(across_index, down_index) {
across_word = across_index[0] // <-- not real, just representing that it becomes an object here.
down_word = down_index[0]
return [across_word, down_word] // <-- This is where my problem is. Not sure how to return a double param for my parent function.
}
The trouble is, the return I am using does not properly pass across_word, down_word .
onUpdateAcrossDown: function(across_word, down_word) {
// How do I get across_word and down_word here properly?
If you want to use the values in an array as parameters to a function, you have to call the function with .apply()
var results = findAcrossAndDownWords( across_index, down_index );
onUpdateAcrossDown.apply(whatever, results);
The .apply() method takes two arguments: the value to use for this in the called function, and an array containing the parameters to pass.
You could, instead of nesting calls, pass the second function as an argument:
findAcrossAndDownWords(across_index, down_index, onUpdateAcrossDown);
function findAcrossAndDownWords(object1, object2, callNext)
{
//do stuff
return callNext(object1, object2);
}
Or, change the function definition of the second function to:
function UpdateAcrossDown(anArray)
{
var obj1 = anArray[0], obj2 = anArray[1];
}
Or, if you're allways going to call the same function:
function findAcrossAndDownWords(object1, object2, callNext)
{
//do stuff
return UpdateAcrossDown(object1, object2);//loses call context
return UpdateAcrossDown.apply(this,arguments);//preserve called context
//or even
return UpdateAcrossDown.apply(this,[object1,object2]);//preserve called context
}

Javascript callback function with parameters [duplicate]

This question already has answers here:
Pass an extra argument to a callback function
(5 answers)
Closed 6 years ago.
This question looks like a duplicate, as the title is nearly replicated. But, my issue seems simpler and I can't find the answer to it.
I have a Javascript function that executes another callback function, it works like this:
<script type='text/javascript'>
firstfunction(callbackfunction);
</script>
where callback function is defined as:
callbackfunction(response) {
if (response=='loggedin'){
// ... do stuff
}}
but I want it to be something like this:
callbackfunction(response, param) {
if (response=='loggedin'){
// ... do stuff with param
}}
My question is, does it work to pass the parameter like this:
<script type='text/javascript'>
firstfunction(callbackfunction(param));
</script>
or am I doing it wrong?
In direct answer to your question, this does not work:
firstfunction(callbackfunction(param));
That will execute callbackfunction immediately and pass the return value from executing it as the argument to firstfunction which is unlikely what you want.
It is unclear from your question whether you should just change firstfunction() to pass two parameters to callbackfunction() when it calls the callback or whether you should make an anonymous function that calls the callback function with arguments.
These two options would look like this:
function firstfunction(callback) {
// code here
callback(arg1, arg2);
}
firstfunction(callbackfunction);
or
function firstfunction(callback) {
// code here
callback();
}
firstfunction(function() {
callbackfunction(xxx, yyy);
});
Use an anonymous function:
function foo( callback ) {
callback();
}
function baz( param ) {
console.log( param );
}
foo( function(){ baz('param') });
Adding parameters when calling a function.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply
xdaz already answered the simple version.
Here is an example with variable amount of parameters.
function someObject(){
this.callbacks=new Array();
this.addCallback=function(cb){
this.callbacks[this.callbacks.length]=cb
}
this.callCallbacks=function(){
//var arr=arguments; this does not seem to work
//arr[arr.length]="param2";
var arr = new Array();
for(i in arguments){
arr[i]=arguments[i];
}
arr[arr.length]="another param";
i=0;
for(i in this.callbacks){
this.callbacks[i].apply(null,arr);
//this.callbacks[i].apply(this,arr);
//this is a ref to currrent object
}
}
this.callCallbacksSimple=function(arg){
for(i in this.callbacks){
this.callbacks[i](arg,"simple parameter");
}
}
}
function callbackFunction(){
for(i in arguments){
console.log("Received argument: " + arguments[i]);
}
}
var ObjectInstance=new someObject();
ObjectInstance.addCallback(callbackFunction);
ObjectInstance.callCallbacks("call callbacks");
ObjectInstance.callCallbacksSimple("call callbacks");
function is key word, you can't use it as function name.
Let say your function name is foo, then you could do like below:
var param = 'what ever';
foo(function(response) {
callbackfunction(response, param);
});
I think this is what you're looking for.
Lets say you're using jQuery ajax to do something, and you're passing it named callbacks. Here we have an onError callback that you might use to log or handle errors in your application. It conforms to the jQuery Ajax error callback signature, except for an extra parameter that you might have wanted to add at the back
function onError(jqXHR, textStatus, errorThrown, yourOwnVariableThing) {
console.error('Something went wrong with ' + yourOwnVariableThing);
}
this is where your function would be called - but you want an extra parameter
$.ajax("/api/getSomeData/")
.done(onDone)
.fail(onError)
.always(onComplete);
So this is what you can do to add the extra parameter
$.ajax("/api/getSomeData/")
.done(onDone)
.fail(onError.bind(this, arguments[0], arguments[1], arguments[2], 'Moo Moo');
.always(onComplete);
arguments is an array in JavaScript that contains all arguments passed to a function, and so you're just passing those arguments along to the callback.
Arguments
Bind

Categories