等待在Ember.js中呈现应用程序之前加载模型

Jus*_*ton 5 javascript ember.js ember-data

我有许多不同的应用程序级模型 - 即当前用户,当前帐户等 - 我想在渲染我的应用程序之前加载.应该如何以及在何处完成?这个问题/答案有很多帮助,但它不包括异步方面.

以下代码完成了我想要的,但加载模型beforeModel(利用它等待解析的承诺)似乎并不正确.我应该加载这些模型ApplicationRoute吗?

App.ApplicationController = Ember.Controller.extend({
  currentAccount: null
});

App.ApplicationRoute = Ember.Route.extend({
  beforeModel: function () {
    var self = this;

    return App.Account.find(...).then(function (account) {
      self.controllerFor('application').set('currentAccount', account);
    });
  }
});
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助!

Meo*_*sky 6

诀窍是从路线的模型方法返回一个承诺.
这将导致路由器转换到App.LoadingRoute路由,直到promise解析(可用于加载指示条/轮等).
当promise解析时,App.LoadingRoute将被停用,原始路由的setupController方法将被召唤.
这适用于ember-data promises,JQuery的$ .ajax promises和ember-model的fetch promises.
只需确保在解决承诺后返回实际模型.
如果承诺被拒绝,这也可以是处理错误的好地方 - 但我会将其留给其他一些问题.

至于你应该加载模型的位置 - 这取决于你的应用程序的用法.
通常你会加载一个模型,其中URL表明你需要该模型 - 经验法则是URL中模型ID的指示.
如果您需要预取一些数据,这当然会改变.

现在有些代码:

App.SomeRoute = Ember.Route.extend({
   model: function(params){
       return App.SomeModel.fetch(params.model_id).then(function(modelData){
           // it is better to return the actual model here, and not the promise itself
           return App.SomeModel.find(params.model_id);
       });

   },
   setupController: function(controller, model){
       controller.set("model", model);
       // do some controller setup here - can be omitted if no setup is needed
       // this will run only after the promise has been resolved.
   }
});

App.LoadingRoute = Ember.Route.extend({
        activate: function(){
            this._super();
            // add some loading indication here
        },
        deactivate: function(){
            this._super();
            // remove loading indication
        }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.


gre*_*ott 6

您想要预加载数据/模型以初始化您的应用程序,并感觉beforeModel不正确?

听起来你需要一个应用程序初始化程序!

你的朋友在这个例子中:

App.deferReadiness(); //暂停应用程序的进度,直到此调用的所有实例(即:多个初始值设定项)与以下调用的实例匹配:

App.advanceReadiness(); //认为这相当于一个promise resolve调用.

1)从您直接查找用户,修改提到的位置以适合您的应用程序设置:

Ember.Application.initializer({
    name: 'loadUser',
    after: 'store',
    initialize: function(container, app) {
        // modify this following to suit how you're determining the account
        var url = 'user/' + currentAccount;
        // tell the app to pause loading until advanceReadiness is declared
        app.deferReadiness();

        // load from JSON 
        Ember.$.getJSON('url').then(function(json) {

            var store = container.lookup('store:main');
            store.load(app.User, json);

            // tell app to start progressing again
            app.advanceReadiness();
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

2)通过元标记:

Ember.Application.initializer({
    name: 'currentUser'
    after: 'store',

    initialize: function(container, app) {
        app.deferReadiness();

        $(function() {
            // Look up an attribute in a meta tag
            var store      = container.lookup('store:main'),
                attributes = $('meta[name="current-user"]').attr('content');

            if (attributes) {
                var obj        = store.load(app.User, JSON.parse(attributes)),
                    user       = App.User.find(obj.id),
                    controller = container.lookup('controller:currentUser').set('content', user);

                container.typeInjection('controller', 'currentUser', 'controller:currentUser');
            }
            app.advanceReadiness();
        });
    }
});
Run Code Online (Sandbox Code Playgroud)

3)通过会话数据:

Ember.Application.initializer({
    name  : 'currentUser',
    after : 'session',
    initialize: function(container, app) {
        var controller = container.lookup('controller:currentUser');
        container.typeInjection('controller', 'currentUser', 'controller:currentUser');
    }
});
Run Code Online (Sandbox Code Playgroud)