Error calling a secondary method via CALLBACK: Uncaught Typeerror: Cannot read Property 'secondarily named' of Undefined

Asked

Viewed 89 times

2

With Javascript (Ecmascript-6), when calling a method via callback, if this method uses another method the following error occurs:

Uncaught Typeerror: Cannot read Property 'nome_do_metodo_secundario' of Undefined

If the method is called directly works perfectly. But if it is called via callback does not work. If you do not have a secondary method, it also works.

How to call via callback, a class method, where this method uses other methods?

Below a code snippet reproducing the error:

class TestOne{
    metodoPrincipal(str_input){
        this.metodoSecundario(str_input);
    }
  
    metodoSecundario(parametro){
        alert("OK: " + parametro);
    }     
}

function chamaViaCallback(callback, msg){
  callback(msg);
}


var test_objeto = new TestOne(); // instancia o objeto

 // funciona chamando diretamente um método secundário
test_objeto.metodoPrincipal('Testando método secundário chamado diretamente!');

// funciona via callback chamando diretamente o método secundário
chamaViaCallback(test_objeto.metodoSecundario, 'método único chamado via callback!');

// não funciona via callback chamando método secundário
chamaViaCallback(test_objeto.metodoPrincipal, 'método secundário chamado via callback!');

3 answers

3


This problem occurs because the function metodoPrincipal loses the reference of the object.

One way to solve this is to pass the object through the bind:

chamaViaCallback(test_objeto.metodoPrincipal.bind(test_objeto), 'Foo');

Another alternative with an arrow function (Arrow Function):

chamaViaCallback( msg => test_objeto.metodoPrincipal(msg), 'Bar');

If you prefer to call the arrow function without arguments and directly pass the message:

chamaViaCallback( () => { test_objeto.metodoPrincipal('Baz'); } );

Example:

class TestOne{
    metodoPrincipal(str_input){
        this.metodoSecundario(str_input);
    }
  
    metodoSecundario(parametro){
        console.log("OK: " + parametro);
    }     
}

function chamaViaCallback(callback, msg){
  callback(msg);
}

var test_objeto = new TestOne(); // instancia o objeto

chamaViaCallback( test_objeto.metodoPrincipal.bind(test_objeto), 'Foo' );
chamaViaCallback( msg => test_objeto.metodoPrincipal(msg), 'Bar' );
chamaViaCallback( () => { test_objeto.metodoPrincipal('Baz'); } );

  • 2

    Note: not only do you need the function arrow to make the second alternative, but I liked the idea of wrap with Arrows

  • 1

    @stderr, thank you so much for your help. It worked fine (+1)

2

When you pass test_objeto.metodoPrincipal to the callback the object function is called, but it will not be able to call the function metodoSecundario because you did not pass the object, but only the function.

Therefore, the object (the variable this) is not defined.

A solution is to pass object and function name (as a string) as callback.

Example, following your code:

function chamaMetodoViaCallback(obj, method, msg){
    obj[method](msg);
}

chamaMetodoViaCallback(test_objeto, "metodoPrincipal", 'método secundário chamado via callback!');
  • thanks for the help. It worked right here. However, in my case, it will be more viable to pass as object same. Stderr’s response was better suited to my situation. (+1 for you)

2

How to call via callback, a method of a class, where this method uses other methods?

If you intend to reference test_objeto.metodoPrincipal without passing test_objeto for chamaViaCallback, use the method Function#bind(instância, argumentos):

test_objeto.metodoPrincipal.bind(test_objeto)

Function#bind returns the same function, covered by predefined instance and arguments.

  • 1

    thanks for the help! It worked right here. (+1 for you.)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.