0

Just as I thought I understood JS scope...

Take this code:

function init() {

    var page;
    var pageName = $('body').data('page');

    switch(pageName) {

        // (there are more switch cases here normally...)                   

        case 'pSearchLatest':
           require(['searchresults'], function (SearchResults) {
               page = new SearchResults().init();
               console.log(page); // <- shows the object!
           });

        default:
           break;

     }

     console.log(page); // <- undefined
     return page;

}

See the console log comments. Why is the second returning undefined when the var page is declared outside of the scope of the switch statement?

EDIT

So I mistakenly thought this was a scope issue but it's down to the asynchronous nature of AMD.

How can I return the value of page in the require scope in the same method without a while loop checking for undefined?

EDIT 2

I did it like this:

function init(callback) {

   case 'pSearchLatest':
      require(['searchresults'], function (SearchResults) {
          page = new SearchResults().init();
          callback(page)
      });
}

and in my page that calls the wrapping init() method:

new PageController().init(function(asyncViewController) {
   App.view = asyncViewController;
});
3
  • 2
    Duplicate of How to return the response from an AJAX call? -- please read that extremely helpful Q&A. The issue is not a scope issue, it's a timing issue. The callback has not yet run when the bottom log runs. The callback to require runs last, after init has terminated. Commented Jun 5, 2013 at 18:40
  • What do you expect it to return? Commented Jun 5, 2013 at 18:41
  • 1
    The require call is async Commented Jun 5, 2013 at 18:43

3 Answers 3

3

You did understand scope correctly. The code in that inner function does indeed assign to the variable in the outer scope.

What you did not understand is asynchronous behaviour. The require function takes a callback function which will be invoked somewhen in the future - when the requested module is available. Yet, it does immediately return and control flow will lead to the console.log statement, which does print undefined - which is the value the page variable has at that time.

You should be able to recognise that since the undefined is logged first, and the log statement in the callback (with the object) executes later, even though it comes above in the code.

Sign up to request clarification or add additional context in comments.

4 Comments

Ah of course! ASYNCHRONOUS module definition. Duh. Thanks, will accept in 9 minutes :D.
eurgh, how do I return page in that init method? I guess I could do a while(page==undefined) thing but that's disgusting right?
@AdamWaite while(page==undefined) will not work, because JS is single-threaded. Set the scene: your callback is waiting for its time to fire, and the thread is busy looping. One day, the callback fires; it comes up to the thread and says "I'm ready to run now!" and thread says, "Sorry, not now, I'm too busy running this loop checking the value of page; you can run when it's done." The callback pleads, "But I'm the one that's suppose to set page for you! Can't you schedule me at all?" to which the thread replies, "Sorry, rules are rules! Guess I'll just run this loop forever, then!"
ha yeh, I'm used to writing in Objective-C and Ruby so Javascript always blows my mind a bit :D. I think I cracked it though, see my update.
2

require is asynchronous, therefore your function did exit first and then processed callback function.

Comments

1

Two possible reasons... you didnt match the case. or the callback where the assignment of the value to page happens hasnt been executed yet. Im guessing its the latter since it would be readily apparent if you case was failing. Look into the documentation for whatever AMD library youre using and see how the execution of the function(s) passed to require are executed.

Also as a generaly rule try to avoid returning values determined by asynchronous calls like this. Instead use some kind of Observer pattern to subscribe to a particular event that can be triggered from different places.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.