在模型钩子中获取一个async hasMany关系



假设我有两个模型,BookChapter

App.Book = DS.Model.extend({
  name: DS.attr(),
  chapters: DS.hasMany('chapter', { async: true })
});
App.Chapter = DS.Model.extend({
  name: DS.attr(),
  book: DS.belongsTo('book')
});

我用的是RESTAdapter

App.ApplicationAdapter = DS.RESTAdapter;

IndexRoute中,假设我想获取第一本书(id = 1)及其相关章节。由于hasMany关系被标记为async: true,我想在模板渲染之前获取这个关联。

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return Ember.RSVP.hash({
      book: this.store.find('book', 1)
    }).then(function(hash) {
      hash.chapters = hash.book.get('chapters');
      return hash;
    })
  },
  setupController: function(controller, model) {
    controller.set('model', model.book);
  }
});

我的索引模板只是简单地显示书名,并遍历它的章节。

<script type="text/x-handlebars" id="index">
  <h3>Book: {{name}}</h3>
  <ul>
    {{#each chapters}}
      <li>{{name}}</li>
    {{/each}}
  </ul>
</script>

当使用mockjax时,我设置模拟响应。

$.mockjax({
  url: '/books/1',
  responseText: {
    book: {
      id: 1,
      name: 'Book 1',
      chapters: [1, 2]
    }
  }
});
$.mockjax({
  url: '/chapters?ids[]=1&ids[]=2',
  responseText: {
    chapters: [{
      id: 1,
      name: 'Chapter 1',
      book_id: 1
    }, {
      id: 2,
      name: 'Chapter 2',
      book_id: 1
    }]
  }
});

问题1:根据RESTAdapter文档,访问book.get('chapters')应该向/chapters?ids[]=1&ids[]=2发出GET请求。然而,我的控制台显示两个单独的请求/chapters/1/chapters/2

问题2:此外,我认为模板在章节请求发生之前呈现,因为模板在我看到对/chapters/1/chapters/2的两个请求之前呈现了一两秒钟。如果我从路由中删除对hash.book.get('chapters')的调用,则会发生同样的问题。换句话说,我认为路由没有发送请求,我认为模板是

这是一个jsbin。你会注意到它没有显示任何章节,因为我没有设置它请求的两个路由(/chapters/1/chapters/2)。

第一个问题的原因很简单:你使用了Dev(Canary)构建的Ember Data,它的行为不同于你可以在EmberJS网站上找到的beta版本。它是前沿的,所以很难判断它是坏了还是即将发生变化。如果你想要与指南一致的行为,我建议使用最新的测试版(烬数据尚未标记为稳定)。

至于第二个:这是期望的行为,因为你正在使用异步请求和承诺。这意味着,您将立即返回结果(不需要等待任何东西),但是这些结果为空,直到解析异步请求。

你可以包装这种行为,(例如)只在async例程完成时注入模板,但是我建议重新考虑它,因为基于个人经验,这不是常见的模式,而且很可能你的应用程序不需要它。

如果你对这些机制的工作原理感兴趣(你不需要这个,它只是为了满足对主题的潜在好奇心):

  • 关于JavaScript线程和伪多线程的文章
  • Wikipedia - AJAX定义
  • Ember.RSVP。Promise - Promise在Ember.js
  • 中使用
  • Kriskowal的Q -不相关的库,但我认为它极大地引入了Promises的概念
  • Ember.js指南-异步方法
  • Ember.js指南-处理异步关系模板

最新更新