RaresI
RaresI

Reputation: 461

How to continue even if Ember.js model hook doesn't load all promises?

I'm loading a route. Its model hook loads some models. Some are fetch from ember store and some are promises requested through AJAX:

model: function () {
        return Em.RSVP.hash({
            //the server data might not be loaded if user is offline (application runs using appcache, but it's nice to have)
            someServerData: App.DataService.get(),
            users: this.store.find('user')
        });

    }

The App.DataService.get() is defined as:

get: function () {
    return new Ember.RSVP.Promise(function(resolve, reject) {   
      //ajax request here
    });
}

Obviously if the request is rejected, the flow is interrupted and I cannot display the page at all.

Is there a way to overcome this?

Upvotes: 4

Views: 909

Answers (2)

RaresI
RaresI

Reputation: 461

Taking into account that Ember.RSVP.hashSettled is not available in my Ember version. I come up with the following solution:

model: function(params) {
        var self = this;
        return new Em.RSVP.Promise(function(resolve, reject){
            // get data from server
            App.DataService.get().then(function(serverData) { //if server responds set it to the promise
                resolve({
                    serverData: serverData,
                    users: self.store.find('user')

                });
            }, function(reason){ //if not ignore it, and send the rest of the data
                resolve({
                    users: self.store.find('user')
                });
            });
        }); 
      }

Upvotes: 0

Ramy Ben Aroya
Ramy Ben Aroya

Reputation: 2423

Ember.RSVP.hashSettled is exactly meant for this purpose.

From tildeio/rsvp.js Github repository:

hashSettled() work exactly like hash(), except that it fulfill with a hash of the constituent promises' result states. Each state object will either indicate fulfillment or rejection, and provide the corresponding value or reason. The states will take one of the following formats:

{ state: 'fulfilled', value: value } or { state: 'rejected', reason: reason }

Here is an example for using it (working JS Bin example):

App.IndexRoute = Ember.Route.extend({
  fallbackValues: {
    firstProperty: null,
    secondProperty: null
  },
  model: function() {
    var fallbackValues = this.get('fallbackValues');
    return new Ember.RSVP.Promise(function(resolve, reject) {
      Ember.RSVP.hashSettled({
        firstProperty: Ember.RSVP.Promise.resolve('Resolved data despite error'),
        secondProperty: (function() {
          var doomedToBeRejected = $.Deferred();
          doomedToBeRejected.reject({
            error: 'some error message'
          });
          return doomedToBeRejected.promise();
        })()
      }).then(function(result) {
        var objectToResolve = {};
        Ember.keys(result).forEach(function(key) {
          objectToResolve[key] = result[key].state === 'fulfilled' ? result[key].value : fallbackValues[key];
        });
        resolve(objectToResolve);
      }).catch(function(error) {
        reject(error);
      });
    });
  }
});

fallbackValues can be useful for managing resolved hash's properties' fallback values without using conditions inside the promise function.

Upvotes: 4

Related Questions