在路由中使用 store.query 时通过 websocket 添加新数据
Adding new data through websocket when using store.query in route
我的应用程序使用基于 ember-phoenix 的 websocket 服务将新记录从 API 推送到商店。我希望这些新记录在添加时呈现在我的模板中。
我有一条路线,其中模型挂钩 returns 过滤查询承诺:
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);
},
});
当您在套接字上收到一条消息时,您可以从您的 websocket 服务触发一个事件,然后在您的路由中订阅它,然后调用 refresh() 重新加载您的模型。
还有 https://github.com/ember-data/ember-data-filter - 重新调整实时数组。
选项 1
您可以使用Ember.Evented to subscribe and dispatch event. I have created twiddle进行演示。
在socket
服务中,
socket
应该扩展 Ember.Evented
class
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
订阅,你可以在resetController
或deactivate
钩子中完成。
resetController() {
get(this, 'socket').leaveSchedule();
get(this, 'socket').off('myModelDataLoaded', this, this.refreshRoute);
}
选项 2.
您可以使用带有观察者和刷新路由的 peekAll 来观看商店。
在你的控制器中,
1. 定义 postModel
computed 属性 这将 return 实时记录数组。
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();
},
}
});
这不是更好的方法,但处理现有代码的一种方法是使用回调。
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);
},
});
我的应用程序使用基于 ember-phoenix 的 websocket 服务将新记录从 API 推送到商店。我希望这些新记录在添加时呈现在我的模板中。
我有一条路线,其中模型挂钩 returns 过滤查询承诺:
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);
},
});
当您在套接字上收到一条消息时,您可以从您的 websocket 服务触发一个事件,然后在您的路由中订阅它,然后调用 refresh() 重新加载您的模型。 还有 https://github.com/ember-data/ember-data-filter - 重新调整实时数组。
选项 1
您可以使用Ember.Evented to subscribe and dispatch event. I have created twiddle进行演示。
在socket
服务中,
socket
应该扩展Ember.Evented
classexport 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
订阅,你可以在resetController
或deactivate
钩子中完成。resetController() { get(this, 'socket').leaveSchedule(); get(this, 'socket').off('myModelDataLoaded', this, this.refreshRoute); }
选项 2.
您可以使用带有观察者和刷新路由的 peekAll 来观看商店。
在你的控制器中,
1. 定义 postModel
computed 属性 这将 return 实时记录数组。
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();
},
}
});
这不是更好的方法,但处理现有代码的一种方法是使用回调。
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);
},
});