2014-09-23 57 views
2

在我的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作爲黑客,但似乎並沒有工作。

任何提示將不勝感激。

回答

5

我會註冊一個session:current對象與user屬性爲空。這將被注入到controllersroutes(不確定注入內部視圖是一個好主意)。

所以在開機時user是未知的,但是路由器出現深度超過application路線,根之前,用戶查找完成:

beforeModelapplication路線,你會加載電流用戶。然後:

  • 要麼你得到了用戶並設置其this.set('session.user', model)
  • ,否則你會在errorapplication路線,在這種情況下,你必須檢查爲什麼要去,如果401然後您可以將用戶重定向到登錄路由this.transitionTo('login')

不要忘記設置標誌上session如果你得到了401使transitionTo將使我們的用戶beforeModel查找,直到我們再發生到達login路線

該代碼被用來加載會話用戶和初始化它可以被放置在該session:current對象,以便能夠從application路線或login控制器調用它。

這是例如我的session初始化(不完全如我所解釋的,但在初始化程序中加載,因此更接近你的)。我使用了一個session模型,因此我做了/session/current,然後讓一個用戶進入(或不是)有正確的ID而不是me然後這會讓商店加載同一用戶與另一個ID,所以有兩次相同用戶爲2個不同的記錄:

app/models/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; 

應用/模板/ 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綁定魔術只會更新會話對象。

+0

@華孚你有代碼示例可以顯示嗎?僅供參考 - 我使用的是ember-simple-auth,每當我在應用程序路徑上使用beforeModel時,即使返回履行的承諾,啓動也會停止。 – ToddSmithSalter 2014-09-23 17:43:15

+0

啊,如果你正在使用'ember-simple-auth',那麼你應該在你的問題中說出它,因爲我不確定它是如何工作的,但肯定會使我的答案的某些部分失效。 我會添加一個示例,但它只是沒有簡單驗證。我聽說過簡單的身份驗證,但沒有使用它,所以不能舉一個例子。是的,在'beforeModel'掛鉤中放置承諾的目標是暫停路由器,也許這是簡單的認證,以某種方式暫停啓動,但通常一旦承諾完成,它應該繼續啓動 – Huafu 2014-09-24 00:03:44

+0

@ToddSmithSalter,剛剛更新東西使用初始化;-) – Huafu 2014-09-24 01:43:03