AngularJs: Have method return synchronously when it calls $http or $resource internally

angularjs, javascript

Solution

In general that's a bad idea. Let me tell you why. JavaScript in a browser is basically a single threaded beast. Come to think of it, it's single threaded in Node.js too. So anything you do to not "return" at the point you start waiting for the remote request to succeed or fail will likely involve some sort of looping to delay execution of the code after the request. Something like this:

var semaphore = false;
var superImportantInfo = null;

// Make a remote request.
$http.get('some wonderful URL for a service').then(function (results) {
  superImportantInfo = results;

  semaphore = true;
});

while (!semaphore) {
  // We're just waiting.
}

// Code we're trying to avoid running until we know the results of the URL call.
console.log('The thing I want for lunch is... " + superImportantInfo);

But if you try that in a browser and the call takes a long time, the browser will think your JavaScript code is stuck in a loop and pop up a message in the user's face giving the user the chance to stop your code. JavaScript therefore structures it like so:

// Make a remote request.
$http.get('some wonderful URL for a service').then(function (results) {
  // Code we're trying to avoid running until we know the results of the URL call.
  console.log('The thing I want for lunch is... " + results);
});

// Continue on with other code which does not need the super important info or 
// simply end our JavaScript altogether. The code inside the callback will be 
// executed later.

The idea being that the code in the callback will be triggered by an event whenever the service call returns. Because event driven is how JavaScript likes it. Timers in JavaScript are events, user actions are events, HTTP/HTTPS calls to send and receive data generate events too. And you're expected to structure your code to respond to those events when they come.

Can you not structure your code such that it thinks canAccess is false until such time as the remote service call returns and it maybe finds out that it really is true after all? I do that all the time in AngularJS code where I don't know what the ultimate set of permissions I should show to the user is because I haven't received them yet or I haven't received all of the data to display in the page at first. I have defaults which show until the real data comes back and then the page adjusts to its new form based on the new data. The two way binding of AngularJS makes that really quite easy.

Problem

Is there a way to wait on a promise so that you can get the actual result from it and return that instead of returning the promise itself? I'm thinking of something similar to how the C# await keyword works with Tasks. Here is an example of why I'd like to have a method like canAccess() that returns true or false instead of a promise so that it can be used in an if statement. The method canAccess() would make an AJAX call using $http or $resource and then somehow wait for the promise to get resolved. The would look something like this: ``` $scope.canAccess = function(page) { var resource = $resource('/api/access/:page'); var result = resource.get({page: page}); // how to await this and not return the promise but the real value return result.canAccess; } ``` Is there anyway to do this?

Original source

Related problems