4
votes

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?

2
you can always just load it in the setupController hook. make the request, on resolve set some controller variable, and on reject, handle the rejection logically. In Ember, while it's idiomatic to get your data in the model hook (and the app auto blocks for your promises), you can (and I often do) make requests that return promises elsewheremistahenry

2 Answers

4
votes

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.

0
votes

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