在我的EmberJS应用程序中,我有一个当前的用户初始化程序,它将用户注入所有控制器,路由和视图。它在登录时效果很好。我需要同步加载当前用户对象,这样我就可以立即检查一些用户权限。
这是我的初始化程序:
App.CurrentUserInitializer - Ember.Initializer.extent({
name: 'current-user',
after: 'authentication',
initialize: function(container, app) {
var store = container.lookup('store:main');
app.deferReadiness();
store.find('user', 'me').then(function (user) {
app.register('session:user', user, {instantiate: false});
_.forEach(['route', 'controller', 'view'], function (place) {
app.inject(place, 'currentUser', 'session:user');
});
app.advanceReadiness();
}).catch(function () {
app.advanceReadiness();
});
}
});
在我遇到这种情况时,是在登录期间。应用程序启动时,将运行初始化程序,但/users/me
路由会返回401错误。如果我没有捕获错误和advanceReadiness,则启动暂停。通过捕获错误,应用程序启动,但登录后初始化程序不会再次运行,因此不会加载当前用户。
我有什么选择?我不能使用@ marcoow推荐的方法向Session添加计算属性,因为我需要在启动时加载用户。
我已经尝试强制将IndexRoute上的用户对象加载为hack,但这似乎不起作用。
任何提示都表示赞赏。
答案 0 :(得分:5)
我注册session:current
对象,user
属性为null。这将被注入controllers
和routes
(不确定注入内部视图是个好主意)。
因此,在启动时user
未知,但用户查找是在路由器深入application
路由之前完成的,根目录:
在beforeModel
路由的application
挂钩中,您将加载该当前用户。然后:
this.set('session.user', model)
error
路线的application
挂钩,在这种情况下,您必须检查原因,如果401
那么您可以将用户重定向到登录路线this.transitionTo('login')
如果您获得session
,请不要忘记在401
上设置一个标记,这样transitionTo
将使beforeModel
的用户查找不再发生,直到我们到达login
路线
用于加载会话用户并初始化它的代码可以放在session:current
对象中,以便您可以从application
路由或login
控制器调用它。
这是我的session
初始化程序(不完全像我解释的那样,但是加载到初始化程序中,因此更接近你所做的)。我使用了session
模型,以便我/session/current
然后让用户(或不是)拥有正确的ID,而不是me
然后会使商店加载具有另一个id的相同用户,因此具有两个相同的用户和两个不同的记录:
应用/模型/ session.js 强>:
import DS from 'ember-data';
import Ember from 'ember';
export default DS.Model.extend({
user: DS.belongsTo('user'),
isAuthenticated: Ember.computed.bool('user.isClaimed')
});
应用/初始化/ session.js 强>:
import Ember from 'ember';
export default {
name: 'session',
after: 'store',
initialize: function (container, app) {
var store = container.lookup('store:main'),
sid = Ember.$.cookie('sid');
// used to register a session
var register = function (session) {
app.register('session:main', session, {instantiate: false});
app.inject('route', 'session', 'session:main');
app.inject('controller', 'session', 'session:main');
};
// used to create a new session and trigger the backend to get details about it
// useful if the server is able to give an existing session while the browser doesn't know about it
// with external providers for example
var newSession = function () {
var session = store.createRecord('session');
// be sure to wipe out any invalid session ID
Ember.$.removeCookie('sid');
register(session);
return session.save().then(function (model) {
// if we got a valid new session, save its ID
Ember.$.cookie('sid', model.get('id'));
}).catch(function () {
Ember.debug('error saving new session: ' + Array.prototype.join.call(arguments, ', '));
});
};
// overall logic ==================
app.deferReadiness();
if (sid) {
// try to load the existing session
store.find('session', sid).then(function (model) {
register(model);
app.advanceReadiness();
}).catch(function () {
// there was a cookie for the session but it might have expired or the server invalidated it
Ember.debug('error loading session: ' + Array.prototype.join.call(arguments, ', '));
newSession().finally(function () {
app.advanceReadiness();
});
});
}
else {
// we don't have any trace of a session, let's just create a new one
newSession().finally(function () {
app.advanceReadiness();
});
}
}
};
应用/ router.js 强>:
import Ember from 'ember';
var Router = Ember.Router.extend();
Router.map(function () {
this.resource('session', {path: '/'}, function(){
this.route('login');
this.route('logout');
});
});
export default Router;
app / templates / application.hbs (作为示例):
<h2 id='title'>Welcome to my app</h2>
{{#if session.isAuthenticated}}
<a {{action 'session.logout'}}>Logout</a>
{{else}}
{{#link-to 'session.login'}}Login{{/link-to}}
{{/if}}
{{outlet}}
然后在登录控制器中,当用户实际登录时,服务器将返回session
模型,并将用户链接到该模型,因此Ember绑定魔法将只更新会话对象。