在Ember.js中渲染应用程序之前,正在等待模型加载
Waiting for models to load before rendering app in Ember.js
我有许多不同的应用程序级别模型,即当前用户、当前帐户等,我希望在呈现应用程序之前加载这些模型。应该如何以及在哪里进行?这个问题/答案帮助很大,但它没有涵盖异步方面。
下面的代码实现了我想要的,但在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);
});
}
});
谢谢你的帮助!
诀窍是从路由的模型方法返回promise
这将导致路由器转换到App.LoadingRoute路由,直到承诺解决(可用于加载指示杆/轮子等)
当promise解析时,App.LoadingRoute将被停用,并且将调用原始路由的setupController方法
这适用于ember数据承诺、JQuery的$.ajax承诺和ember模型的fetch承诺
只需确保在解决承诺后返回实际模型即可
如果承诺被拒绝,这也是一个处理错误的好地方——但我将把这留给其他问题。
至于你应该在哪里加载你的模型,这取决于你的应用程序的使用情况
通常,您会加载一个模型,其中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
}
}
希望这能有所帮助。
您想预加载数据/模型来初始化应用程序,但觉得beforeModel不正确?
听起来你需要一个应用程序初始化器!
在这种情况下,你的朋友:
应用程序.deferReadness()//停止应用程序的进程,直到该调用的所有实例(即:多个初始化程序)与以下调用的实例匹配:
App.advanceReadness()//认为这相当于promise解析调用。
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();
});
}
});
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();
});
}
});
3) 直通会话数据:
Ember.Application.initializer({
name : 'currentUser',
after : 'session',
initialize: function(container, app) {
var controller = container.lookup('controller:currentUser');
container.typeInjection('controller', 'currentUser', 'controller:currentUser');
}
});
我通过在ApplicationRoute中使用嵌套的Promises和afterModel方法成功地完成了这项工作。
App.ApplicationRoute = Ember.Route.extend({
model: function() {
// load the reservation (a globally needed model)
return App.Reservation.fetch().then(function(reservations) {
return reservations.get('firstObject');
});
},
afterModel: function() {
// Load all other globally needed models
var self = this;
return App.Gender.fetch().then(function(genders) {
self.controllerFor('application').set('genders', genders);
return App.FilterAttribute.fetch().then(function(filterAttributes) {
self.controllerFor('application').set('filterAttributes', filterAttributes);
//return App.SomeOtherModel...
});
});
},
setupController: function(controller, model) {
controller.set('reservation', model);
}
});
工作非常完美:-)应用程序将保留在LoadingRoute中,直到加载所有记录为止。注意,我使用的是Ember模型,但这应该没有什么区别,它只需要返回一个Promise。
- 跟踪在页面加载时应用内联样式的JavaScript
- Chrome扩展没有't在重新加载之前考虑期权价值
- 为什么元素的宽度在页面加载之后和那一刻之后不同
- JavaScript链接在点击时不起作用;函数在页面加载时工作
- 如何在页面加载中使用Jquery/Javascript确定img源
- 如何在页面加载后更改“选定”选项
- JS页面在后台加载时显示动画
- 使用javascript在页面加载时取消选中所有复选框
- Adobe Air SDK在页面加载时调整窗口大小
- 使用CSS在页面加载时从中心向外扩展线条
- 如何在页面加载时设置函数的条件
- jQuery-在页面加载时执行一个函数
- AngularJs|Don'在成功加载所有指令htmls之前,不显示页面
- 在javascript中使用split函数希望在页面加载时拆分url
- 是否可以在 spotfire 文本区域中显示图像/消息以等待加载数据
- 等待加载的数据,然后在 AngularFire 0.9.0 中返回
- 我如何在页面加载的第一件事就是调用setTimeout,然后等待五秒钟
- JS代码在页面加载时触发,而不是等待click事件
- 在显示所有元素之前,正在等待加载页面
- 在显示加载旋转器之前请等待