somdow
somdow

Reputation: 6318

Calling objects in jQuery as a callback, not working properly

I'm trying to understand something about calling objects forth but i am missing something. Below i wrote dummy code (that works) so i can illustrate my issue. Here is some code.

html:

<button id="test">tst</button>

js:

var testObj = {
    text: function(){
        console.log("is it working???");
    }
}

//on button click
$('#test').click(function(){
    console.log(testObj.text());
});

now, with this, when i click that button, it works fine and the console shows "is it working" as it's supposed to.

As a test when i do the same thing but remove the parenthesis from the object call, just leaving it as

$('#test').click(function(){
    console.log(testObj.text);
});

the console expectantly shows it to me as an object. The console in Google Chrome specifically says "function testObj.text()". Essentially, it does not run the code inside which again is fine.

Here is the problem.

When i try to call the testObj object as a callback method it does not work.

Here is what i have:

$('#test').click(function(){
    $(this).animate({"font-size": "20"}, 3000, "swing",  testObj.text());
});

With this code directly above, what ends up happening is that although "is it working" does come up in the console, it doesn't wait for the 3 seconds to then activate the callback, the callback fires off as soon as the button is clicked. Essentially it's miss-firing the callback.

Now, when i use the same code, but remove the parenthesis from the object call, then it works as its supposed to. The animation plays and after the 3 seconds when its done, then the callback fires and shows "is it working" on the console as its supposed to.

$('#test').click(function(){
    $(this).animate({"font-size": "20"}, 3000, "swing",  testObj.text);
});

Looking all the way above on the first example where when i removed the parenthesis, the console showed it to me as an object and did not run the code inside, i don't understand why it now works inside the callback with the parenthesis removed.

My question is, why is this happening? I've gone up and down on google but not even sure what i'm searching for.

Upvotes: 2

Views: 64

Answers (3)

kockburn
kockburn

Reputation: 17626

The answer is pretty straight forward.

Here is an example of a basic asynchronous function adding a + b and calling the callback function when it's finished.

var addition = function(a, b, callback){
  setTimeout(function(){
    callback(a+b);
  }, 0);
}

Now lets go back to the problem you came upon. I want to add 1 + 1 together and have the callback called when the addition ends.

If I do this:

var func = function(result){
  console.log(result);
}

addition(1, 1, func());

Callback is not being used correctly as a callback function. Sure you have it in the right place, but the () means you want to run the function. So here is step by step what happens when you run it like that:

addition(1, 1, func());
  1. func() gets called first and attempts to console.log(result) which result is undefined since we never put it as a parameter when we called the function
  2. There is no return result from func() so your third parameter in addition isn't a function.
  3. Addition finally gets called but fails since the callback is not a function.

Now the correct way would be to not add the (). This ensures that func does not get called before addition gets called. You actually send the function uncalled to addition. When addition finishes it's 1 + 1 it'll call the func (which happens to be named callback) with the result as the parameter.

Upvotes: 1

David
David

Reputation: 219016

The parentheses cause the function to execute. When you pass a callback, you pass the name of the function as a reference to it. (Understand that in JavaScript functions are "first class citizens" and can be used as objects like any other.)

So when you do something like this:

var x = someObject.someFunction;

You are setting x to that function reference. Which allows you to execute it as a function:

x();

But when you do this:

var x = someObject.someFunction();

You are executing the function and setting its result to x. So this:

$(this).animate({"font-size": "20"}, 3000, "swing",  testObj.text());

Executes the testObj.text() function (which writes to the console) and sets its result (which is undefined) as the callback, resulting in an error when jQuery tries to invoke that callback. But this:

$(this).animate({"font-size": "20"}, 3000, "swing",  testObj.text);

Doesn't execute the function. It passes the function as a reference which jQuery will later execute.

Upvotes: 4

Jaromanda X
Jaromanda X

Reputation: 1

Essentially it's miss-firing the callback.

$(this).animate({"font-size": "20"}, 3000, "swing",  testObj.text());

That sets the callback to be the result of running (immediately) the testObj.text function

$(this).animate({"font-size": "20"}, 3000, "swing",  testObj.text);

That sets the callback to be the testObj.text function

All the code you wrote before that is confusing you because you're console logging the result of a function that doesn't return a value, but when run, logs to the console itself ...

From that code, I can't see how you determined that passing the result of the function is the correct thing to do when you want to use a function as a callback to be called back

Upvotes: 1

Related Questions