This question already has answers here:
Pass an extra argument to a callback function
(5 answers)
Closed 6 years ago.
I want to something similar to this:
function AjaxService()
{
this.Remove = function (id, call_back)
{
myWebService.Remove(id, CallBack)
}
function CallBack(res) {
call_back(res);
}
}
so my calling program will be like this:
var xx = new AjaxService();
xx.Remove(1,success);
function success(res)
{
}
Also if I want to add more parameters to success function how will I achieve it.
Say if I have success function like this:
var xx = new AjaxService();
//how to call back success function with these parameters
//xx.Remove(1,success(22,33));
function success(res,val1, val2)
{
}
Help will be appreciated.
Use a closure and a function factory:
function generateSuccess (var1,var2) {
return function (res) {
// use res, var1 and var2 in here
}
}
xx.Remove(1,generateSuccess(val1,val2));
What you're passing here is not the generateSuccess function but the anonymous function returned by generateSuccess that looks like the callback expected by Remove. val1 and val2 are passed into generateSuccess and captured by a closure in the returned anonymous function.
To be more clear, this is what's happening:
function generateSuccess (var1,var2) {
return function (res) {
// use res, var1 and var2 in here
}
}
var success = generateSuccess(val1,val2);
xx.Remove(1,success);
Or if you prefer to do it inline:
xx.Remove(1,(function(var1,var2) {
return function (res) {
// this is your success function
}
})(val1,val2));
not as readable but saves you from naming the factory function. If you're not doing this in a loop then Xinus's solution would also be fine and simpler than my inline version. But be aware that in a loop you need the double closure mechanism to disconnect the variable passed into the callback function from the variable in the current scope.
You can pass it as anonymous function pointer
xx.Remove(1,function(){
//function call will go here
success(res,val1, val2);
});
one way to do this:
function AjaxService {
var args_to_cb = [];
this.Remove = function (id, call_back, args_to_callback_as_array) {
if( args_to_callback_as_array!=undefined )
args_to_cb = args_to_callback_as_array;
else
args_to_cb = [];
myWebService.Remove(id, CallBack)
}
function CallBack(res) {
setTimeout( function(){ call_back(res, args_to_cb); }, 0 );
}
}
So you can use it like this:
var service = new AjaxService();
service.Remove(1,success, [22,33]);
function success(res,val1, val2)
{
alert("result = "+res);
alert("values are "+val1+" and "+val2);
}
I usually have the callback execute using a setTimeout. This way, your callback will execute when it gets the time to do so. Your code will continue to execute meanwhile, e.g:
var service = new AjaxService();
service.remove(1, function(){ alert('done'); }); // alert#1
alert('called service.remove'); // alert#2
Your callback will execute after alert#2.
Of course, in case of your application, it will happen so automatically since the ajax callback itself is asynchronous. So in your application, you had better not do this.
Cheers!
jrh
Related
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.
I have the following problem:
I'm trying to implement a Callback in JavaScript. Now I just made it with a global variable which holds my callbacl function. Here is the example:
_callbackFkt = null;
requestCompleted = function(oControlEvent) {
console.log("Callback: " + _callbackFkt.toString());
};
myLibRequest = function(callback) {
// some code, which is attached to the requestComplete event when ready
_callbackFkt = callback;
};
Now I try to call the functions which use the callback:
myLibRequest(function () {
// callback function 1
});
myLibRequest(function () {
// callback function 2
});
myLibRequest(function () {
// callback function 3
});
the result in the console is:
Callback: function () {
// callback function 3
}
How can I define the callback to be bound to one function call and not global available? I want the result:
Callback: function () {
// callback function 1
}
Callback: function () {
// callback function 2
}
Callback: function () {
// callback function 3
}
There are several ways to do what you are trying to do, but your basic problem is that you want a list of event handlers, but you are only assigning a single value.
To modify what you are currently doing:
_callbackFkts = [];
myLibRequest = function(callback) {
// some code, which is attached to the requestComplete event when ready
_callbackFkts.push(callback);
};
Then, when you want to execute the callbacks:
_callbackFkts.forEach(function(callbackFkt) {
callbackFkt();
});
But, this global mechanism is a bit messy. You might consider some encapsulation (untested, but you get the idea):
function Events() {
this.callbacks = [];
}
Events.protototype.bind = function(callback) {
this.callbacks.push(callback);
};
Events.prototype.executeAll = function(params) {
this.callbacks.forEach(function(callback) {
callback.apply(this, params);
}
}
Then you can use it like this:
var events = new Events();
events.bind(function() {
//callback function 1
});
events.bind(function() {
//callback function 2
});
events.bind(function() {
//callback function 3
});
events.executeAll('with', 'parameters');
Finally, you might just use an off-the-shelf event library. There are lots. One quick google search finds this.
Having a global as the callback will only work if myLibRequest() contains only synchronous code (which I assume it doesn't).
Remove the global, and use the callback that is passed in as an argument.
Assuming you have some async call in there, and you call requestCompleted when it's done. Add an argument so requestCompleted receives the callback, instead of referenceing the global.
requestCompleted = function(oControlEvent, callback) {
console.log("Callback: " + callback.toString());
};
myLibRequest = function(callback) {
myAsyncFunction(function(){
// async complete
requestCompleted('event', callback);
});
};
I am trying to get the name of the last executed function using JavaScript and this following code is working for me but need to find any other method is available? please help me:
var fname;
function fn()
{
fname="fn()";
}
function fn1()
{
fname="fn1()";
}
function fexecute()
{
setTimeout(fname, 0);
}
I want to get finally executed function name and when i call fexecute() function at that time call last executed function.
If you want to execute a function name that you have in a string, you will have to do some besides just pass the string to setTimeout(). The best option would be to save a reference to the function directly rather than a string name.
var lastFunc;
function fn()
{
lastFunc=fn;
}
function fn1()
{
lastFunc=fn1;
}
function fexecute()
{
// execute previous function after a short timer
setTimeout(lastFunc, 0);
}
If you don't need the setTimeout(), then you can execute the last function like this:
function fexecute()
{
// execute previous function
lastFunc();
}
Just use arguments.callee.name
var fname;
function anyFunction () {
fname = arguments.callee.name;
}
function anyOtherFunction () {
fname = arguments.callee.name;
}
Call the functions normally like anyFunction(); and anyOtherFunction();
I am struggling to totally understand callbacks and i am stumbling at the final hurdle.
Within JS I am calling a function which then calls a PHP function using a dojo rpc Json Service. I have stepped through the function in firebug and the PHP is executing and returning me the correct response via the callback but I don’t know how to return the value to the initial JS variable that invoked the JS function? E.g.
JS Function 1
Function one(){
Var test = getPhp(number);
}
function getPhp(number)
{
this.serviceBroker = new dojo.rpc.JsonService(baseUrl + '/index/json-rpc/');
var result = serviceBroker.phpFunc(number);
result.addCallback(
function (response)
{
if (response.result == 'success')
{
return response.description;
//I am trying to pass this value back to the
//var test value in function one
}
}
);
}
Basically i now need to pass response.description back to my var test variable in function one.
Any help is appreciated
This is not possible, since the callback is run asynchronously. This means that the getPhp function returns before the callback is executed (this is the definition of a callback, and one of the reasons asynchronous programming is hard ;-) ).
What you want to do is create a new method that uses the test variable. You need to call this method when the callback is executed.
i.e.
function one(result) {
var test = result;
// Do anything you like
}
function getPhp(number, callback) {
this.serviceBroker = new dojo.rpc.JsonService(baseUrl + '/index/json-rpc/');
result.addCallback(
function (response)
{
if (response.result == 'success')
{
callback(response.description);
}
}
);
}
getPhp(number, function(result) { one(result); });
This last method creates an 'anonymous function' that is passed to the getPhp function. This function gets executed at the time the response arrives. This way you can pass data to the one(number) function after the data arrives.
The short answer is that you can't.
Do whatever you want to do with the data in the callback or functions you call from the callback. You can't return anything from it.
A much cleaner answer:
getPhp(number);
function one(data){
var test = data;
// do what you want
}
function getPhp(number)
{
this.serviceBroker = new dojo.rpc.JsonService(baseUrl + '/index/json-rpc/');
var result = serviceBroker.phpFunc(number);
result.addCallback(
function (response)
{
if (response.result == 'success')
{
one(response.description);
}
}
);
}
How can I callback to a function in an object?
json_post('get_tracks', 'json.request.php?get=tracks', 'genreId='+id+'&perPage=70&page=1', 'rtn_tracks');
Instead of making a callback to rtn_tracks() I want to do it to this.rtn()
How can I define this in the callback string?
Here is the code:
function stream_tracks(){
this.get = function(id){
json_post('get_tracks', 'json.request.php?get=tracks', 'genreId='+id+'&perPage=70&page=1', 'rtn_tracks');
};
this.rtn = function(json_obj){
this.cnstr(json_obj);
};
this.cnstr = function(json_obj){
alert('test');
};
}
Stream_tracks = new stream_tracks();
var XMLHTTP = {};
function json_post(request_uid, uri, get_str, callback_function, callback_var){
request_uid += Math.floor(Math.random()*999999).toString();
if(window.XMLHttpRequest){
XMLHTTP[request_uid] = new XMLHttpRequest();
}
else if(window.ActiveXObject){
XMLHTTP[request_uid] = new ActiveXObject('Microsoft.XMLHTTP');
}
XMLHTTP[request_uid].open('POST', uri, true);
XMLHTTP[request_uid].setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
XMLHTTP[request_uid].onreadystatechange = function(){
if(XMLHTTP[request_uid].readyState == 4){
if(callback_function){
eval(callback_function+'('+XMLHTTP[request_uid].responseText+(callback_var ? ', callback_var':'')+')');
}
}
}
XMLHTTP[request_uid].send(get_str);
}
Instead of using a string for callback, use a method.
var my = {
start : function (s, callback) {
callback(s);
},
callback: function(s) {
}
}
You cannot use:
my.start("Hello World", my.callback)
Since this will cause the method to be processed without connection to the object my but you can do this.
my.start("Hello World", function(s) { my.callback(s); });
You can pass functions as objects in Javascript, you don't need to pass the function name and use eval. If your callback should be called as a member of a class, you need to pass along the class instance as well. E.g. add a callback context argument to your json function:
function json_post(request_uid, uri, get_str, callback_function, callback_var, callback_context){
/*... snip ...*/
XMLHTTP[request_uid].onreadystatechange = function(){
if(XMLHTTP[request_uid].readyState == 4)
{
if(callback_function){
/* The call() function lets you call a function in a context */
callback_function.call(
callback_context || this,
XMLHTTP[request_uid].responseText,
callback_var
);
}
}
};
XMLHTTP[request_uid].send(get_str);
}
Then you would call it like so:
json_post('get_tracks', 'json.request.php?get=tracks', 'genreId='+id+'&perPage=70&page=1',
this.rtn, // callback function
null, // callback var
this // callback context
);
Here's a good tip though: Use a framework! It will make your day a lot easier.
Ok so there are a couple of things that you need to do and it might make more sense if you have a read about closures.
Firstly you'll need to make a reference to the this variable so you can access it inside your callback without overwritting it.
function stream_tracks(){
var obj = this;
Then if you want to refer to properties of that class/object from within its other methods you just use obj.this.
The second thing you should do is pass the callback as a function not as a string. It will also be more efficient as you will be able to do away with the eval function.
this.get = function(id){
json_post(
'get_tracks',
'json.request.php?get=tracks',
'genreId='+id+'&perPage=70&page=1',
function(){ obj.rtn(); }
);
};
Wrapping the callback in the anonymous function forms the closure and allows the function to use the variables from class. Also if you do it this way you can pass any parameters through at the same time as the function and do away with the extra parameters in the parent function.