简体   繁体   中英

Handle rejected promise when Ember Data hasMany property is accessed by template

Is there a standard way of handling errors when a 'findHasMany' call fails? Use case:

Model: App.User
{
DS.hasMany('comments', {'async': true});
}

Template

{{#each comment in comments}}
<p>{{comment.title}}</p>
{{/each}}

The issue is that when the lazy loading of comments fails, due to some server issue for example, I want to be able to respond to that error in the UI (by routing somewhere else, showing a popup about errors on the page, etc). At the moment the promise just rejects. I thought that Ember Data might have some hook on the ManyArray for cases like this, but it doesn't seem to, and the store seems to define precisely nothing as the action to carry out in such cases: https://github.com/emberjs/data/blob/v1.0.0-beta.8/packages/ember-data/lib/system/store.js#L1758 - the promise is given a 'resolve' method, but not a reject method.

My options seem to be either subclassing the store, and adding in some reject code there, or subclassing DS.PromiseArray and observing the 'isRejected' property. Any thoughts would be very welcome!

EDIT: This issue seems to boil down to the fact that, when handling models defined in a route, Ember and Ember Data work well together (you can catch rejecting promises in an error action) there is no similar structure for async requests directly through a template. One solution might be to have an observer in the controller that observes something like 'model.isError', but a failing hasMany relationship does not trigger an error on the owning model. I suppose instead I can do 'comments.isRejected', but again, I would have to code that in for every controller that has a model with a hasMany relationship, in other words, all of them, which doesn't seem very satisfactory. If models had an observable enumerable property (like "hasManyIsError": {comments: false, posts: true}) then it would be easy to observe any of them with 'hasManyIsError.length

Assuming a var called user that has been fetched, you'd do this:

var itWorked = function(comments) { return comments; }
var itFailed = function(error) { return error; }

user.get("comments").then(itWorked, itFailed);

async: true means it'll get using a promise... so you can use then... you can't do that on a relationship that doesn't specify async: true.

[edit] sorry I just realised it might not be obvous that whatever you put in the itFailed function will eval when the request for comments fails, and likewise inversely for itWorked... :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM