在路由中使用store.query时,通过websocket添加新数据

时间:2017-01-19 22:11:28

标签: ember.js websocket ember-data

我的应用正在使用基于ember-phoenix的websocket服务将新记录从API推送到商店。我希望这些新记录在我们的模板中添加后再显示。

我有一个模型钩子返回过滤后的查询承诺的路由:

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,则会呈现新记录,但我希望我的路由只根据日期查询参数加载所有记录的子集。

似乎我唯一的选择就是在将新记录推送到商店时重新加载路线的模型。是否有可能从服务中做到这一点?如果没有,我可能想探索一种不同的方法吗?

我的套接字服务的相关部分如下:

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 个答案:

答案 0 :(得分: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。如您所知,这将调用beforeModelmodelafterModel方法。

如您所知,计算属性是惰性的,当您访问它时,它将被计算。因此,如果您未在模板中使用它,则只需在this.get('myModel')方法

中添加init即可

控制器文件

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 :(得分:1)

当您在套接字上收到消息时,可以从websocket服务触发事件,然后在路由中订阅它,然后调用refresh()重新加载模型。 还有https://github.com/ember-data/ember-data-filter - 返回实时数组。

答案 2 :(得分: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();
  },

});

在套接字服务中调用回调方法,

 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);
  },
});