2017-01-19 34 views
4

我的應用正在使用基於ember-phoenix的websocket服務將新記錄從API推送到商店。我希望這些新記錄在添加時在我的模板中呈現。在路由中使用store.query時通過websocket添加新數據

我在模型鉤子返回一個過濾查詢承諾的路線:

import Ember from 'ember'; 

const { 
    get, 
    inject, 
} = Ember; 

export default Ember.Route.extend({ 
    socket: inject.service(), 

    model(params) { 
    return this.store.query('my-model', {filter: {date: params.date}}) 
    }, 

    afterModel() { 
    get(this, 'socket').joinSchedule(); 
    }, 

    resetController() { 
    get(this, 'socket').leaveSchedule(); 
    }, 

}); 

當新記錄通過WebSocket的推到了店裏,他們沒有被我的模板渲染,因爲如何store.query作品。如果我將store.query更改爲store.findAll,則會呈現新記錄,但我希望我的路由僅基於日期查詢參數加載所有記錄的子集。

這似乎是我的唯一選擇是在將新記錄推送到商店時重新加載路線模型。有沒有可能從服務中做到這一點?如果不是,我可能想探索一種不同的方法嗎?

我Socket服務的相關部分如下:

import Ember from 'ember'; 
import PhoenixSocket from 'phoenix/services/phoenix-socket'; 

const { 
    get, 
    inject, 
} = Ember; 

export default PhoenixSocket.extend({ 
    session: inject.service(), 
    store: inject.service(), 

    joinSchedule() { 
    const channel = this.joinChannel(`v1:my-model`); 

    channel.on('sync', (payload) => this._handleSync(payload)); 
    }, 

    _handleSync(payload) { 
    get(this, 'store').pushPayload(payload); 
    }, 
}); 

回答

3

選項1
您可以使用Ember.Evented訂閱和分派事件。我已創建twiddle進行演示。

socket服務,

  • socket應該擴展Ember.Evented

    export default PhoenixSocket.extend(Ember.Evented, {

  • 更新存儲之後,你可以觸發myModelDataLoaded將派遣訂閱myModelDataLoaded的所有功能。

     _handleSync(payload) { 
         get(this, 'store').pushPayload(payload); 
         this.trigger('myModelDataLoaded'); //this will call the functions subscribed to myModelDataLoaded.   
        }

在路線,

  • 您可以訂閱myModelDataLoaded
 
afterModel() { 
     get(this, 'socket').joinSchedule(); 
     get(this, 'socket').on('myModelDataLoaded', this, this.refreshRoute); //we are subscribing to myModelDataLoaded 
    } 
  • 定義refreshRoute功能和呼叫refresh功能。

     
        refreshRoute() { 
         this.refresh(); //forcing this route to refresh 
        } 
    
  • 爲了避免內存泄漏需要off訂閱新資料,你可以做到這一點無論是在resetControllerdeactivate掛鉤。
     
    resetController() { 
        get(this, 'socket').leaveSchedule(); 
        get(this, 'socket').off('myModelDataLoaded', this, this.refreshRoute); 
    } 
    

選項2
你可以觀看商店使用peekAll觀察員和刷新路線。

在你的控制器中,
1.定義postModel計算屬性,它將返回活動記錄數組。
2.定義postModelObserver依賴於postModel.[]這將確保每當商店更新新行時,它將被觀察到myModelObserver,它會發送行動refreshRoute路由。我們將在那裏撥打refresh。如您所知,這將稱爲beforeModel,model,afterModel方法。

正如你所知,計算屬性是懶惰的,當你訪問它只有它會被計算。所以,如果你沒有在模板中使用它,那麼就在init方法添加this.get('myModel')

控制器文件

import Ember from 'ember'; 
const { computed } = Ember; 
export default Ember.Controller.extend({ 
    init() { 
     this._super(...arguments); 
     this.get('postModel');//this is just to trigger myModel computed property 
    }, 
    postModel: computed(function() { 
     return this.get('store').peekAll('post'); 
    }), 
    postModelObserver: Ember.observer('postModel.[]', function() { 
     this.send('refreshRoute'); 
    }) 
}); 

路由文件 - 定義動作refreshRoute用於刷新,因爲refresh僅提供路線。

import Ember from 'ember'; 

const { 
    get, 
    inject, 
} = Ember; 

export default Ember.Route.extend({ 
    socket: inject.service(), 
    model(params) { 
     return this.store.query('my-model', { filter: { date: params.date } }) 
    }, 

    afterModel() { 
     get(this, 'socket').joinSchedule(); 
    }, 

    resetController() { 
     get(this, 'socket').leaveSchedule(); 
    }, 
    actions:{ 
     refreshRoute() { 
      this.refresh(); 
     }, 
    } 
}); 
+1

感謝您的詳細答覆!根據@xoma在上面發佈的回覆,我最終做了你在方案1中提出的建議,但由於你花時間爲將來的人們記錄它,所以我會給你信任。 –

0

這不是一個更好的方法,但是一種處理現有代碼的方法是使用回調。

import Ember from 'ember'; 

const { 
get, 
inject, 
} = Ember; 

export default Ember.Route.extend({ 
    socket: inject.service(), 

    model(params) { 
    return this.store.query('my-model', {filter: {date: params.date}}) 
    }, 

    afterModel() { 
    let cb = (myModelRecord) => { 
     this.get('model').push(myModelRecord); 
    }; 
    get(this, 'socket').joinSchedule(cb); 
    }, 

    resetController() { 
    get(this, 'socket').leaveSchedule(); 
    }, 

}); 

調用回調方法Socket服務,

import Ember from 'ember'; 
import PhoenixSocket from 'phoenix/services/phoenix-socket'; 

const { 
    get, 
    inject, 
} = Ember; 

export default PhoenixSocket.extend({ 
    session: inject.service(), 
    store: inject.service(), 

    joinSchedule(cb) { 
    const channel = this.joinChannel(`v1:my-model`); 

    channel.on('sync', (payload) => cb(this._handleSync(payload))); 
    }, 

    _handleSync(payload) { 
    return get(this, 'store').pushPayload(payload); 
    }, 
}); 
相關問題