Javascript Asynchronous Return Value

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;
});

Answers:

Answer

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.

Answer

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

Answer

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.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.