调用异步模型的Ember js controllerSetup可以使用断点但不能没有

时间:2014-03-09 04:05:45

标签: javascript ember.js

强制版信息:

"DEBUG: Ember      : 1.6.0-beta.1+canary.ffa2c83c"
"DEBUG: Ember Data : 1.0.0-beta.7+canary.d55198c2"
"DEBUG: Handlebars : 1.3.0"
"DEBUG: jQuery     : 2.1.0"

我有像这样设置的余烬数据模型

App.User = DS.model.extend({
    username: DS.attr(),
    sites: DS.hasMany('site', {async:true})
});

这样的路线设置如下:

App.SitesRoute = Ember.Route.extend({
    setupController: function (controller, model) {
        this.controllerFor('auth').get('model.sites').then(function(sites){
            controller.set('model', sites);
        });
    });
 });

auth控制器为我提供了当前登录的用户,我希望站点路由仅显示与当前登录用户相关的站点。

然而,这不起作用并抛出错误

"Error while loading route: App.SitesRoute<.setupController"

有趣的是,如果我在那里抛出一个断点,这个setupcontroller挂钩实际上是有效的,没有错误发生,数据加载到用户界面。

这让我相信这里的承诺加载存在问题,但我无法解决原因。我会想到,当'model.sites'的承诺完成后,控制器模型会被设置,而这又会填充内容和我的ui。但事实似乎并非如此。

有什么想法吗?我在这里做错了什么?

修改1

这是一种具有类似结果的变体。如果我在路由的模型钩子中的return语句上放置一个断点,它就可以工作。否则它不会

App.SitesRoute = Ember.Route.extend({
    model: function () {
        return this.controllerFor('auth').get('model.sites');
    },
    setupController: function (controller, model) {
        controller.set('model', model);
    }
});

修改2

好的,这是使这段代码有效的东西。但在我看来,与docs相反的是:

  

“如果数据是异步可用的,您可以返回   来自模型钩子的承诺,Ember将等到那个承诺   在渲染模板之前解决。“

我原以为调用self.controllerFor('auth')。get('sites')是一个承诺,如果'sites'关系被标记'asyc:true'我错了吗?

所以我可以这样做并且它有效,我想这有点模拟断点:

App.SitesRoute = Ember.Route.extend({
    model: function() {
        var self = this;
        return new Ember.RSVP.Promise(function(resolve) {
            Ember.run.later(function() {
                    resolve(self.controllerFor('auth').get('sites'));
                  }, 3000);
        });
    },
    setupController: function(controller,model) {
            controller.set('content', model);
    }
});

编辑3

好的,我找到了一些有用的东西,我现在也会参与其中,但我仍然对不了解正在发生的事情或原因感到不满。我忽略了一些事情,即我正在使用ember-data-django-rest-adapter我无法判断这是否是导致问题的原因,尽管有几个小时的调试ember和适配器的内部结构。

这里没有进一步的麻烦是最终工作:

App.SitesRoute = Ember.Route.extend({
    setupController: function(controller,model) {
        this.controllerFor('auth').get('content').then(function (user) {
           user.get('sites').then(function (sites) {
               controller.set('content', sites);
           });
        });
    }
});

如果对其他方法不起作用的原因有任何见解,将不胜感激。

2 个答案:

答案 0 :(得分:1)

我要做的是让所有控制器都知道当前用户是将currentUserController注入到ember初始化程序中的所有控制器中。然后,你可以通过像this.get('currentUser')那样访问控制器中的任何一点来获取currentUser。]

在你的情况下,我会尝试这个,看看它是否有效:

model: function() {
  return this.controllerFor('auth').get('sites');
},

setupController: function(controller,model) {
   model.then(function(response) {
      controller.set('content', response);
   }
}

答案 1 :(得分:1)

我发现当我有一个使用async: true的模型关系时,我可以期待当我得到那个关系时,结果是一个承诺,例如:

var stuff = model.get('relatedCollection');
var actualStuff;

if (typeof stuff.then === 'function') {
  stuff.then(function (collection) {
    actualStuff = collection;
  });
} else {
  actualStuff = stuff;
}

以上是伪代码,用于说明当您定义模型依赖关系时使用aysc: true时,您很可能会在get相关集合时看到承诺。

我注意到,当承诺得到解决时,即使您设置了断点,当您get相关集合时,您可能会看到实际的集合而不是承诺。

因此,当我使用aysc: true时,我通常会使用分支代码来首先检查结果是否可以typeof thing.then === 'function'如果是这样,我会将指定的值视为承诺;并且在解析promise之后使用thenable语法来获取模型的实际集合。