2014-09-12 51 views
1

我使用的是localStorage的適配器ember.jsEmber local-storage如何在控制器中使用hasMany with async:true?

下面是這一問題的JSbin:http://jsbin.com/lejizo/9/edit?html,console,output

有了這些機型:如果你不

/* Models */ 
App.List = DS.Model.extend({ 
    name: DS.attr('string'), 
    // DOES NOT WORK:: items: DS.hasMany('item') 
    items: DS.hasMany('item', {async: true}) 
}); 

App.Item = DS.Model.extend({ 
    name: DS.attr('string'), 
    list: DS.belongsTo('list') 
    }); 

灰燼數據引發錯誤」 t使hasMany異步。順便提一下,數據在localstoarge。我初始化這樣的:

var FIXTURES = { 
    'list': { 
     records: { 
      '1': { 
       id: '1', 
       name: 'The List', 
       items: ['1','2'] 
      }, 
      '2': { 
       id: '2', 
       name: 'The Second List', 
       items: ['1','3'] 
      } 
     } 
    }, 
    'item': { 
     records: { 
      '1': { 
       id: '1', 
       name: 'item 1', 
       list: '1' }, 
      '2': { 
       id: '2', 
       name: 'item 2', 
       list: '1' 
      }, 
      '3': { 
       id: '3', 
       name: 'item 3', 
       list: '1' 
      } 
     } 
    } 
} 

localStorage.setItem('DS.LSAdapter', JSON.stringify(FIXTURES)); 

不管怎麼說,使得items: DS.hasMany('item', {async: true})使應用流暢運行。

問題是如果我嘗試從控制器訪問items他們不是一個對象,它們只是一個承諾!這迫使我們用下面的辦法:

list.get('items').then(function(items) { // must use then 
    items.forEach(function(item){ 
     console.log(item.get('id')); 
    }); 
}); 

這似乎是尷尬的我,總是提防hasMany關係,要小心你如何使用它們,而不是隻與相關對象爲任何其他關係工作..

這是正常的還是我錯過了什麼? 有沒有一種解決方法,不定義它們async:true,因爲所有的數據已經在本地存儲? 作爲最佳實踐,我們是否應該始終在所有相關實體的控制器中使用?

回答

2

這似乎是尷尬的我,總是提防的hasMany關係,要小心你如何使用它們,而不是隻與相關的對象爲無任何其他關係工作..

那會很尷尬,這就是爲什麼你不必這樣做。 ;)在大多數情況下,Ember將自動監視屬性更新並相應地傳播它們。那是什麼意思?這意味着你不應該擔心價值是一種承諾; 使用它,好像它不是一個

總之,Ember使用一種特殊的承諾來觀察房地產更新。因此,讓我們假設你有下面的模板:

{{#each item in model.items}} 
    {{item.name}} 
{{/each}} 

如果model.items是一個異步hasMany關係,灰燼仍然會做正確的事。當模板首次呈現時,將不會有數據。 你的each循環將不會產生任何結果。但是Ember正在觀看model.items屬性的更新。當它有更新時(如承諾解決時),Ember將再次運行模板。這一次,數據將會在那裏,並且它將按照您的預期正常工作。

同爲性質也是如此:

function() { 
    return this.get('model.items').filter(function(item) { 
     return !!item; 
    }); 
}.property('[email protected]') 

此屬性將返回一個空數組它運行的第一次。但是,當承諾解決時,Ember將再次運行該屬性併產生您想要的結果。

在這個背後有很多事情正在進行,但是您通常不需要擔心,直到您遇到一些更復雜的用例。如果您想了解更多,我建議您查看以下資源:

  1. The RSVP Promise library
  2. Ember's guide on asynchrony
  3. ObjectProxyArrayProxy
  4. PromiseProxyMixin

編輯:如果你想修改關係,例如,添加一個新的項目,做這樣的事情:

actions: { 
    addPost: function(post) { 
     this.get('model.posts').then(function(posts) { 
      posts.addObject(post); 
     }); 
    } 
} 
+0

我注意到他們在模板中工作得很好。我不知道.property()也處理它們。謝謝!儘管如此,我還是不相信......如果在控制器操作中,我必須用model.idems做些什麼?看起來,model.get('items')返回一個promise,而不是一個數組!請檢查exmaple:http://jsbin.com/lejizo/9/edit?html,console,output – RaresI 2014-09-12 13:08:42

+0

我用一個小例子更新了我的答案,大多數人修改hasMany關係。你可能最初與異步鬥爭,但它會來找你。只記得一個**非常重要的事情:異步並不意味着緩慢。 – GJK 2014-09-12 13:33:21