等待嵌套 Promise 完成
Waiting for Nested Promises to complete
我在 Ember 控制器中构建了一个复杂的对象图。
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')
})
所以,为了设置所有这些,我基本上是在尝试
- 创建容器,
- 然后,创建细节,其中可能有很多
- 然后,创建项目,其中将有尽可能多的细节
- 等待所有承诺解决
- 在容器装满所有东西后,对 "activate" 容器启动自定义休息操作。
代码看起来像这样(咖啡),经过简化,但我认为要点就在那里
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
当所有的 promises 解决时,一切都是我想要的,但是,allSettled 启动得太早了,因为它在细节解决之前就已经达到了,所以项目还没有被创建,所以里面没有任何东西大批。如果我将详细信息添加到数组中,也会发生这种情况,因为它在项目创建之前就已达到。
我唯一能做的就是让单独的数组跟踪不同的承诺,并在每个承诺解决时都有一个嵌套的 allSettled,但这开始感觉很麻烦,我想知道是否有更好的方式。
谢谢!
您需要 return
来自 then
回调的承诺,以便您可以正确地 unnest 它们。因此,首先 return
该回调中的项目承诺,并得到一个承诺,即您可以在该循环中立即实际推送到您的 promises
数组:
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
现在您得到了一组可以实际传递给 allSettled
的承诺。您也不能在容器的 then
回调之外调用它(因为那时 promises
仍然是空的),但在回调内部,您可以再次 return 该承诺为阵列,以便你展平你的链。
我建议不要使用 forEeach
并手动构建该数组,只需使用 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
我在 Ember 控制器中构建了一个复杂的对象图。
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')
})
所以,为了设置所有这些,我基本上是在尝试
- 创建容器,
- 然后,创建细节,其中可能有很多
- 然后,创建项目,其中将有尽可能多的细节
- 等待所有承诺解决
- 在容器装满所有东西后,对 "activate" 容器启动自定义休息操作。
代码看起来像这样(咖啡),经过简化,但我认为要点就在那里
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
当所有的 promises 解决时,一切都是我想要的,但是,allSettled 启动得太早了,因为它在细节解决之前就已经达到了,所以项目还没有被创建,所以里面没有任何东西大批。如果我将详细信息添加到数组中,也会发生这种情况,因为它在项目创建之前就已达到。
我唯一能做的就是让单独的数组跟踪不同的承诺,并在每个承诺解决时都有一个嵌套的 allSettled,但这开始感觉很麻烦,我想知道是否有更好的方式。
谢谢!
您需要 return
来自 then
回调的承诺,以便您可以正确地 unnest 它们。因此,首先 return
该回调中的项目承诺,并得到一个承诺,即您可以在该循环中立即实际推送到您的 promises
数组:
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
现在您得到了一组可以实际传递给 allSettled
的承诺。您也不能在容器的 then
回调之外调用它(因为那时 promises
仍然是空的),但在回调内部,您可以再次 return 该承诺为阵列,以便你展平你的链。
我建议不要使用 forEeach
并手动构建该数组,只需使用 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