I would like to load an entire collection and then just peel off records to use as models one at a time, without doing a roundtrip to the server every time.
I've figured out how to use Ember.Deferred to return a promise, but I can't get the promise to resolve at the right time. The following code just outputs "Found 0" ever time:
App.PersonRoute = Ember.Route.extend({
model: function(params) {
var name = "Erik";
var promise = Ember.Deferred.create();
App.people = App.Person.find();
App.people.then(function() {
console.log('Found ' + App.people.get('length'));
var person = App.people.findProperty('name', name)
promise.resolve(person);
});
return promise;
}
});
If I wrap the body of the then() in a setTimeout, and make it wait a couple seconds, everything works great.
Is there another event I can somehow bind to? I tried App.people.on('isLoaded'), but isLoaded is always true.
Thanks!
Is there another event I can somehow bind to?
Indeed there is an event you can listen to and that is didLoad
.
I tried App.people.on('isLoaded'), but isLoaded is always true.
As for isLoaded
there was a lot of confusion about this, see here for example, the confusion comes from the fact that the isLoaded
flag is set to true by design when the store has finished loading the RecordArray
for the records, even when initially empty because no record was already available locally. Then when the request to the server comes back the RecordArray
will be populated with the records received from the backend, and bindings will kick off and your templates are updated.
As stated in the guides:
A record that is both loaded and clean means that is has received information about its attributes and relationships from the server, and no changes have been made locally on the client.
Was is stated above is what makes didLoad
fire.
For more model related events you can listen to have a look at the guides under model lifecycle
Now to your setup, you could rewrite your code to something like this:
App.PersonRoute = Ember.Route.extend({
model: function(params) {
var name = "Erik";
var promise = Ember.Deferred.create();
App.people = App.Person.find();
App.people.on('didLoad', function() {
console.log('Found ' + App.people.get('length'));
var person = App.people.findProperty('name', name)
promise.resolve(person);
});
return promise;
}
});
Hope it helps.
If the promise isn't resolving at the right time, I think it would be a (fairly major)bug in Ember/data. I would suggest filling a bug with Emberjs/data.
I suspect though that your use of the different promise may be causing this bug.
App.Person.find
is already returning a promise. You should use that promise itself when returning from the model()
. Also to resolve that promise you simply return a result.
The implementation style for Promises
that you have used is typically needed when you are integrating some external async api that doesn't support Promises
.
I would refactor your model()
like so. That might fix your async timing issue.
App.PersonRoute = Ember.Route.extend({
model: function(params) {
var name = "Erik";
var promise = App.Person.find();
promise.then(function() {
console.log('Found ' + App.people.get('length'));
return App.people.findProperty('name', name)
});
return promise;
}
});
I've found the docs on the Q library to be very useful when figuring out best way to use promises. Ember uses RSVP which is a different library but the principles are similar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With