2015-06-01 181 views
0

我有一個複雜的對象圖,我正在建立一個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. 創建conatainer,
  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,但是這開始感覺非常毛茸茸,我想知道是否有更好的方法。

謝謝!

+0

沒有真正熟悉咖啡的腳本,但內部或外部容器創建的諾言allSettled聲明? Nvm從@Bergi看到答案 – jcbvm

回答

2

您需要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在當時仍然是空的),您不能在回調中調用該回調,但在回調中,您可以再次爲該陣列返回該承諾,以便平滑鏈條。

而且我建議你不要使用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 
+0

@ Kingpin2k:感謝編輯提示!不過,我猜想這只是使用胖箭頭而已。我試圖在原始代碼中儘可能少地使用:-) – Bergi

+0

是的,我認爲這是一個胖箭頭的事情,但不熟悉CS(除CS <-> JS網站外),我想我會避免試圖採取行動,因爲我知道我在和他們做什麼,因爲害怕把它搞砸;) – Kingpin2k

+0

非常棒的答案和建議,那就是訣竅! – DVG