Reputation: 17480
I have a complicated object graph I'm building up in an Ember Controller.
export default Container({
username: DS.attr('string'),
items: DS.hasMany('item')
})
export default SomeDetail({
foo: DS.attr('string')
})
export default Item({
detail_type: DS.attr('string'),
detail_id: DS.attr('number'),
container: DS.belongsTo('container')
})
So, to set all this up, I'm basically trying to
The code looks like this (coffee), simplified but I think the gist is there
promises = []
store = @store
items = @get('itemsInMyController')
store.createRecord('container',
username: @get('username')
).save().then(container) ->
items.forEach (item) ->
store.createRecord('detail',
# Set Properties
).save().then (detail) ->
item = store.createRecord('item',
# Set Properties
)
promsies.push item
item.save()
Ember.RSVP.allSettled(promsies).then (responses) ->
# Perform Activate Action
When all the promises resolve, everything is how I want it, however, allSettled is firing way too soon, because it's reached before the details have resolved, so the items haven't been created, so there's nothing in the array. This also happens if I add the details to the array, because it's still reached well before the items have been created.
The only thing I can thing of is to have separate arrays tracking the different promises, and having a nested allSettled as each one resolves, but this is starting to feel pretty hairy, and I'm wondering if there's a better way.
Thanks!
Upvotes: 0
Views: 702
Reputation: 664307
You need to return
promises from your then
callbacks so that you can properly unnest them. So first return
the item promise from that callback and get a promise that you can actually push to your promises
array immediately in that loop:
promises = []
@get('itemsInMyController').forEach (item) =>
promise = @get('store').createRecord('detail',
# Set Properties
).save().then (detail) =>
item = @get('store').createRecord('item',
# Set Properties
)
item.save() # this returns a promise
) # and `promise` resolves with that result eventually
promises.push promise
Now you got an array of promises that you can actually pass to allSettled
. You must not call that outside of the then
callback for the container as well (because promises
would still be empty by then), but inside the callback, and you can again return that promise for the array so that you flatten your chain.
And I'd recommend not to use forEeach
and manually build up that array, just use map
:
@store.createRecord('container',
username: @get('username')
).save().then (container) =>
promises = @get('itemsInMyController').map (item) =>
@get('store').createRecord('detail',
# Set Properties
).save().then (detail) =>
@get('store').createRecord('item',
# Set Properties
).save()
Ember.RSVP.allSettled promises
.then (responses) ->
# Perform Activate Action
Upvotes: 3