How to wait for async angularJS call to complete if concurrent call requested the data being still loaded?

StackOverflow https://stackoverflow.com/questions/23264725

I have an angular service/resource combo that does async call to server to get User Preferences. It is called UserPreferencesService and got a method load:

 /// UserPreferencesService.load method
 CommonService.asyncCall(UserPreferencesResource.getAll, {username: userName}).then(
            function (data) {
                userPreferenceData = data;
  }

where asyncCall stands for trivial angular async server call that returns deferred.promise. It is called at some point.

Same UserPreferencesService also has method getCurrentProject() to return these preferences to controllers that are interested in, with calling code:

var myControllerInit = function()
 {
        var prj = UserPreferencesService.getCurrentProject();
 }

I have a situation that some controller (that displays "current project" on screen) calls "getCurrentProject" WHILE "load" async call is in progress, so getCurrentProject does not return neeeded data, as these are not fully loaded yet.

How I can make it so that UserPreferencesService.getCurrentProject() will "wait" till the request resolves, if it is underway, and only then return the value? I suppose I can try to use promises, and I would like to have elegant, angular-style solution to the problem.

有帮助吗?

解决方案

Disclaimer: I'm not familiar with Angular and the way it handles promises and asynchronicity.


In JavaScript, you can't block until a promise is resolved; you can only make code that relies on a promise return its own promise, chained to the original one. In other words: you can't have synchronous code that relies on async code.

If I understand correctly, you want to defer any action on the PreferencesService until it is loaded. You can't do this synchronously, but you can make each of its other methods return a promise that depends on its async loading.

If this is what you want, you should guard each of the service's methods with .then on the original loading promise. This promise should be resolved once, when the service is loaded. Further invocations of other methods will be resolved immediately.

Example:

function UserPreferenceService() {
  var loadedPromise = null;
  var userPreferenceData = null;

  this.load = function() {
    if (loadedPromise == null)
      loadedPromise = CommonService.asyncCall(UserPreferencesResource.getAll, {userName: userName})
        .then(function(data) { userPreferenceData = data; });

    return loadedPromise;
  };

  this.getCurrentProject = function() {
    return this.load().then(function() { 
      return doSomethingWith(userPreferenceData);
    });
  }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top