-1

Suppose I have this as an option to a jQuery widget:

    function oneFunc()
    {
     var myVar;

       //there is some widget calling
       $.widget("ui.combobox", $.ui.autocomplete, {
                options: {
                       source: function (request, response){////doing something with myVar, request and response}
                }
       });
    }

Now I want to separate out the function (request, response) using callback

So, I want something like this:

function oneFunc()
{
     var myVar;
     //there is some widget calling
        $.widget("ui.combobox", $.ui.autocomplete, {
                options: {
                       source: myCallBack
       });
}

function myCallBack(request, response){
//I can get request and response here by default but not myVar
//doing something with myVar, request and response
}

So, I can't access myVar. I have to pass it there. but how to do that?

EDIT: I don't want to use global variables request, response are default values that I can get in myCallBack anyway.

Better if anonymous function can be avoided.

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
soham
  • 1,508
  • 6
  • 30
  • 47

3 Answers3

2

You can do this by using Function.apply or Function.call

function oneFunc(myCallback)
{
     this.myVar = 1;
    var request = "request";
    var response = "response"
     //there is some widget calling
     myCallback.apply(this,[request,response]);
}

function callback(request, response){
   console.log(request);
    console.log(response);
    console.log(this.myVar);
}

oneFunc(callback);

The above outputs

request
response
1

As you have delegated the this keyword to the callback method allowing it to access any variables declared in the original method.

Live example: http://jsfiddle.net/hFsCA/

Note the apply line can also be replaced with (Thanks @AlessandroVendruscolo)

myCallback.call(this,request,response);

Not that it makes too much difference - but for completeness!

So wrapping that back into your (now updated) example:

function oneFunc(callback)
{
   this.myVar = 1;
   var self = this;
   //there is some widget calling
   $.widget("ui.combobox", $.ui.autocomplete, {

            options: {
                 source: function (request, response){
                        callback.call(self,request,response);
                 }
            }
   });

}
Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • I'd use `call`, because you're creating one array that is not really needed. `myCallback.call(this,request,response);` – Alessandro Vendruscolo Jul 08 '13 at 11:52
  • `request` and `response` are not local to the function. they are only accessible after `source` is there. So `request` is undefined there. – soham Jul 08 '13 at 11:56
  • Yeah! in that case I don't need to use `call` also. I can just send the variable. But I don't want to use anonymous function. – soham Jul 08 '13 at 12:01
  • @soham.m17 - you're not making any sense. Of course you could just send the variable - I guess the advantage is that if you had 100 variables they would all be accessible in the `this` context. Not sure what you mean by "anonymous function". In any case, you asked a question and got an answer. If you don't like the answer think up a better question. – Jamiec Jul 08 '13 at 12:03
  • Well, the question states "how to pass additional arguments to callbacks..." I don't think your answer addresses that thing in particular. Anyway, it's a good solution avoiding the main course. Thanks. – soham Jul 08 '13 at 12:09
2

If you want to access myVar inside your separated callback function, I would make it explicit in the declaration:

function myCallBack(request, response, myVar) 
{
}

This makes it easier to keep track of when you see it in your code later on. Then, you write a proxy function like this:

source: function(request, response) {
    return myCallBack.call(this, request, response, myVar);
}

If you want a more complex scope or myVar needs to be changed in both scopes, you need an object:

var myScope = {
    myVar: null
};

// ...

source: function(request, response) {
    return myCallBack.call(this, request, response, myScope);
}

Then, inside the callback:

function myCallBack(request, response, myScope) 
{
    // use myVar as myScope.myVar
}
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • Actually it would be better if I can pass the argument to the callback not using any anonymous function. Although this thing works. But I don't want to use anonymous function. What I am thinking is that we can just place `myCallBack` inside `oneFunc()` also. That also solves the problem. As `myVar` then would be in scope of `myCallBack` also. But again, that's not elegant code. – soham Jul 08 '13 at 12:24
  • @soham.m17 This is starting to sound like an XY problem; you don't like to use anonymous functions, but obviously the state inside `oneFunc()` must be somehow transferred. What exactly does `myVar` contain, what are you writing? – Ja͢ck Jul 08 '13 at 12:31
  • It's a simple string. That is modified in `myCallBack`. – soham Jul 08 '13 at 12:55
  • No, `myVar` is sent to `myCallBack` and reused in `oneFunc()` again. I think I am sounding ambiguous. I simply want to use `call backs` with additional parameter capability. – soham Jul 08 '13 at 13:14
  • @soham.m17 Well, then you need anonymous functions to gather the scope used for your callback, it's as simple as that. – Ja͢ck Jul 08 '13 at 13:17
1

I don't if jQuery is internally using any anonymous function or not. But I solved it by this:

function oneFunc()
{
     var myVar;
     //there is some widget calling
        $.widget("ui.combobox", $.ui.autocomplete, {
                options: {
                       source: $.proxy(myCallBack, this, myVar)
       });
}

function myCallBack(myVar, request, response){
//I can access myVar, request and response
//doing something with myVar, request and response
}

Other experienced people can comment on this, I guess.

soham
  • 1,508
  • 6
  • 30
  • 47