【问题标题】:Waiting for Nested Promises to complete等待嵌套 Promise 完成
【发布时间】:2015-08-15 10:18:39
【问题描述】:

我在 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')
})

所以,要设置这一切,我基本上是在尝试

  1. 创建容器,
  2. 然后,创建细节,其中可能有很多
  3. 然后,创建项目,其中将包含尽可能多的细节
  4. 等待所有承诺解决
  5. 一旦容器拥有所有东西,就会触发自定义休息操作以“激活”容器。

代码看起来像这样(咖啡),简化但我认为要点在那里

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

当所有的承诺都解决了,一切都是我想要的,然而,allSettled 太快了,因为在细节解决之前就已经达到了,所以项目还没有创建,所以数组中没有任何内容。如果我将详细信息添加到数组中也会发生这种情况,因为它仍然在创建项目之前就已经达到了。

我唯一能做的就是让单独的数组跟踪不同的承诺,并在每个解决方案时都有一个嵌套的 allSettled ,但这开始感觉很麻烦,我想知道是否有更好的方法。

谢谢!

【问题讨论】:

  • 对coffee脚本不是很熟悉,但是allSettled语句是在容器创建的promise里面还是外面? Nvm 查看@Bergi 的回答

标签: ember.js coffeescript promise


【解决方案1】:

您需要从您的then 回调中return 承诺,以便您可以正确地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 仍然为空),但在回调内部,您可以再次为数组返回该承诺,以便您展平您的链。

我建议不要使用 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

【讨论】:

  • @Kingpin2k:感谢编辑提示!不过我猜想只使用粗箭头更符合 CS 习惯。而且我试图在原始代码中尽可能少的东西:-)
  • 是的,我认为这是一个胖箭头,但不熟悉 CS(除了 CSJS 网站),我想我会避免表现得像我知道我在做什么正在和他们一起做,因为害怕把事情搞砸;)
  • 我今天花了几个小时试图弄清楚这一点。直到模板被渲染之后,嵌套的 Promise 才得到解决。使用 RSVP.all() 返回一个数组是关键。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-09
  • 1970-01-01
  • 1970-01-01
  • 2016-12-18
相关资源
最近更新 更多