Using PromiseArrayMixin states VS route loading states


#1

Hi all,

I have a route that makes a query so I’m getting back a PromiseArray in my model hook. I would like to bypass the sync. wait. Just wondering which approach is now better:

  1. Traditional approach of setting up loading and error substate template, so that they appear async. This however needs duplication of template code since I’d like to the page to look like loaded except for a specific region.

  2. Wrap the model hook return in an object { promise: this.store.query(...) } and set it up manually in setupController (controller.set('model', model.promise)). Then leverage isPending and isFulfilled in the template to display state. I prefer this since I have less template code duplication.

My question is, am I going off track with 2?


#2

I have ended up using Option 2 quite a bit lately as it allows me to have a little more control over how my loading state is rendered. I don’t think that’s going off track at all…(It also means that any sub-routes that you have can begin loading immediately — perhaps a good perk of that choice).


#3

Thanks Spencer! I have opted for option 2 as well. My concern is that I’m not feeling great with passing PromiseArray down to my components and templates (like CP watching model.content instead of model, view watching isPending instead of isUpdating). The difference between PromiseArray and AdapterPopulatedRecordArray is slightly annoying, but I’d rather my templates and components work with the default route behaviour (handling anything that behaves like AdapterPopulatedRecordArray).


#4

Well, that doesn’t mean that you have to pass the promise down to the components, templates, etc. You could do something like this:

export default Ember.Route.extend({
  model() {
    return {
      promise: this.store.query(...)
    };
  },
  setupController(controller, model) {
    controller.set('isLoading', true); // So you can show a loading state
    model.promise.then(resolvedModel => {
      controller.set('model', resolvedModel);
    }, error => {
      // Do something to handle the error. 
    }).finally(() => {
      controller.set('isLoading', false);
    });
  }
});

This way, you’ve got a little more control over what happens when the promise resolves. I’ve done this in a few places and seems to work well.


#5

Yeah I see. I actually have multiple endpoints being called in the model hook (and just switching from RSVP.Hash to Object) so it wouldn’t be too pretty to set so many properties in the Controller (thisIsLoading, thatIsLoading, etc.). But that’s a good idea! I’ll use it for one or two of the models where needed.

Thanks again for all the replies!