david Turner
david Turner

Reputation: 33

Variable Undefined Scope

Here is my code:

function example() { 
     var post = object.get("owner");
         post.fetch({
            success: function(post) {
               window.titles = post.get("username");
               console.log(window.titles);
            }
         });
     console.log(window.titles);
} 

The first log works successfully. Outside of the method, the second log prints as undefined. Why?

Upvotes: 0

Views: 55

Answers (4)

Chrissi
Chrissi

Reputation: 349

It is helpful to think of asynchronous data as only being defined inside the success callback. While it may not always be true, it's the only time when it's ALWAYS defined. Anytime that you are outside the success callback, the data may not have been retrieved yet and the callback may not have run yet.

This is what your program looks like if you remove the asynchronous call:

function example() { 
     var post = object.get("owner");
     post.fetch();
     console.log(window.titles);
}

It is more obvious here that window.titles is undefined.

On a separate thread, elsewhere, once post.fetch() is complete, this will be executed (at some time in the future, who knows when... it could be in 1 ms, it could take 1 day, you really cannot know):

(function(post) {
   window.titles = post.get("username");
   console.log(window.titles);
})()

Do you see now what the problem is? window.titles has not been set yet. post.fetch() has been called, but the success callback has not returned yet.

There is no way to do what you're asking, which is, to retrieve data before you've actually retrieved data. Anything that requires the predictability of having fetched the data, must happen inside the callback (Edit: Or you may use promises or deferreds or etc.. but those are more complicated for what you are trying to do here). So that is why your console.log() inside the success callback works, and the one outside will probably never work.

Upvotes: 0

Shomz
Shomz

Reputation: 37701

It works in the outside function, but not right away because async calls take some time. That's the nature of JS.

The easiest way "out of it" is to move all the code that depends directly on the results of your async function into another function and then just run it from within the success callback.

Something like this:

function example() { 
     var post = object.get("owner");
         post.fetch({
            success: function(post) {
               window.titles = post.get("username");
               otherImportantCode(); // call the remaining code from here
            }
         });
     console.log(window.titles); // won't work here
} 

function otherImportantCode() {
     console.log(window.titles); // see, it works here, outside the example function
     // ... the rest of the code depending on window.titles
}

When you're ready for more advanced handling of such issues, learn about promises and events.

Upvotes: 0

Marco Bonelli
Marco Bonelli

Reputation: 69367

The post.fetch function is asynchronous, this means that it needs a callback to call when it's finished, otherwise you'll never know when the function has been completed. Asynchronous functions run separately from the rest of the code.

When you call post.fetch it start by its own and it will not stop the script, so right after calling post.fetch, the next line of code is executed, which is actually console.log(window.titles). But window.titles has not yet been defined, since that post.fetch is still working.

When post.fetch finishes working the given callback function gets executed, and then the window.titles variable gets defined. So if you want to log window.titles you have to put the console.log() only inside the callback of post.fetch.

Upvotes: 0

simpletron
simpletron

Reputation: 739

This is async call. The inner will be executed after the POST success. Meanwhile the outer execute after you start to send POST. The window.titles is defined when the POST success

So the at the time outer call is executed, the window.titles is undefined. You should have look at this http://api.jquery.com/jquery.ajax/

Upvotes: 1

Related Questions