botenvouwer
botenvouwer

Reputation: 4432

What about variable scopes inside a callback function

If I have a callback function within a callback function I can't reach the variables declared inside the first callback.

See example (Uses some jquery):

my fiddle

Why is this?

Or

What am I doing wrong!?

I am using this in the following:

$('<div/>').html(data).find('load').each(function(id, deze) {

        var method = $(deze).attr("method");
        var animate = $(deze).attr("animate");
        var locatie = $(deze).attr("id");
        var html = $(deze).html();

        if(!method){
            method = 'overide';
        }

        if(!locatie){
            error('A002','No loadloc');
        }

        if(!html){
            html = '';
        }

        if(!animate){
            animate = false;
        }
        else if(animate == 'fade'){
            var effectout = 'fade';
            var timeout = 100;
            var optionsout = {
                easing: 'swing'
            };

            var effectin = 'fade';
            var timein = 600;
            var optionsin = {
                easing: 'swing'
            };
        }
        else{
            animate = false;
            error('A006','Animation: "' + animate + '" does not exist');
        }

            //here I make callback or direct function call
        if(animate){
            $('#' + locatie).hide(effectout, optionsout, timeout, load());
        }
        else{
            load();
        }

    function load(){
        console.log('hallo');
        console.log(html);
        if(method == 'overide'){
            $('#' + locatie).html(html);
        }
        else if(method == 'tablerow'){
            var html = $('tr', deze).html();
            $('#' + locatie).html(html);
        }
        else if(method == 'append'){
            $('#' + locatie).append(html);
        }
        else if(method == 'prepend'){
            $('#' + locatie).prepend(html);
        }
        else{
            error('A007','load method: "' + method + '" does not exist');
        }

        if(animate){
            $('#' + locatie).show(effectin, optionsin, timein);
        }
    }

    });

Upvotes: 2

Views: 187

Answers (3)

asifrc
asifrc

Reputation: 5841

The reason it doesn't work is because the keyword this changes meanings within the context of load() since you're defining a function using function load(). There are several ways of getting around this; here's one:

Before:

if(animate){
            $('#' + locatie).hide(effectout, optionsout, timeout, load());
        }
        else{
            load();
        }

use

var load = (function(el) {
    return function() {
        console.log('hallo');
                //It seems I can't reach html and other variables here
        console.log(el.html);
        if(method == 'overide'){
            $('#' + el.locatie).html(el.html);
        }
        else if(method == 'tablerow'){
            var html = $('tr', deze).html();
            $('#' + el.locatie).html(el.html);
        }
        else if(method == 'append'){
            $('#' + el.locatie).append(el.html);
        }
        else if(method == 'prepend'){
            $('#' + el.locatie).prepend(el.html);
        }
        else{
            error('A007','load method: "' + el.method + '" does not exist');
        }

        if(el.animate){
            $('#' + el.locatie).show(el.effectin, el.optionsin, el.timein);
        }
    };
})(this);

What I did there was to change all references to this with el. And then I injected this as el by using the following format:

load = ( function(el) {  return yourFunction() {...}; })(this);

Let me know if that makes sense and if it works for you :)

Upvotes: 0

Bergi
Bergi

Reputation: 665574

Why is this?

It is not. You can simply access something, it is in the scope of the load function that you posted.

What am I doing wrong!?

You're not passing the load function itself as the callback, but it's result - you're immediately calling it (without arguments). You want

$('#' + locatie).hide(effectout, optionsout, timeout, load);
//                                                        ^^
//It seems I can't reach html and other variables here
console.log(this.html);

That's not a variable, that's a property of this (and the this keyword points to different things in the different calls). What you want is a simple variable:

console.log(html);

Same story for this.locatie and the others.

Upvotes: 3

Smern
Smern

Reputation: 19086

I changed your code a bit and I believe this is what you were trying to do:

http://jsfiddle.net/smerny/2M6k3/

var anothercallbackfunctiontriggerthing = function(cb) {
    cb();
}

$('.something').each(function(id, value) {
        var something = 'something';
        var load = function(){
                    // can't reach something here
                    console.log(something);
        }
        anothercallbackfunctiontriggerthing(load);
});

As load() didn't return anything, I assume you were wanting to pass it as a callback (load) and then call it from within anothercallbackfunctiontriggerthing. The above code will print "something" for each .something.

Upvotes: 1

Related Questions