0

I am relative new to node.js and I ran into a problem where a function is returning undefined. I use console.log to make sure that it returns the proper value and it does. But in the script that makes the call to the function shows as undefined. I think this may be an issue with async programming? I am trying to learn more on how promises work in node.js. What am I doing wrong?

The reason why I believe that it is a problem with async is because console.log is printing to the console undefined before the console.log in getCurrentFrameName();. var name is being assigned undefined.

frameHandler.switchToFrame('top_page');

var name = frameHandler.getCurrentFrameName();

console.log(name);

The console.log in this method prints to the console after the console.log in the code above. The value printed to the console of name is top_page.

this.getCurrentFrameName = function()
{
    driver.executeScript('return self.name').then(function(name) {
        console.log(name);
        return name;
    });
};
Grim
  • 2,398
  • 4
  • 35
  • 54

2 Answers2

1

You can do this:

this.getCurrentFrameName = function(callback) {
    driver.executeScript('return self.name').then(function(name) {
        return callback(name);
    });
};

and then call it like this:

frameHandler.getCurrentFrameName(function(name) {
    console.log(name);
});

this will fix your problem, but yes, is a sync problem.

fuelusumar
  • 797
  • 8
  • 15
0

Yes, this is an issue with asynchronous programming. You cannot return a value from an asynchronous callback.

This is because the callback waits for the asynchronous script to execute, and so, node immediately passes control to the next line after the callback.

In your case, console.log(name); gets called before the callback is executed. Hence, the undefined.


The simplest solution to the current situation is to perform the necessary computations within the callback itself.

However, in more complicated situations (such as, callback within callback) you can easily end up with what is known as callback hell.

There are several ways to deal with callback hell: one of them is something called Promise.

What a Promise does essentially, is that it brings a sense of linearity to the code, thus making it easier to understand and maintain.

In your case, you can do this:

this.getCurrentFrameName = function() {

    var myPromise = driver.executeScript('return self.name');

    myPromise.then(function(name) {
        // Do all computation with `name` here
    });

};
Soubhik Mondal
  • 2,666
  • 1
  • 13
  • 19
  • The computation that you want to do with the `name` argument (passed to the callback) has to be done in the callback itself. – Soubhik Mondal Feb 29 '16 at 15:52
  • Can you return the callback or promise and get the name argument value either way? – Grim Feb 29 '16 at 16:03
  • Check my updated answer. And yes, you can return the `Promise` object, but you would still have to write the computation within the `then` clause. You cannot return the `name` argument, nor the callback. – Soubhik Mondal Feb 29 '16 at 16:09