简体   繁体   English

通知余烬数据有关服务器的更改

[英]Inform ember-data about server changes

I am currently planning a complex application using ruby on rails and ember.js. 我目前正在计划在Rails和ember.js上使用ruby的复杂应用程序。 What I have seen about ember-data so far is that it caches records automatically; 到目前为止,我对ember-data的了解是它会自动缓存记录。 post.comments will first result in a Ajax-call to fetch all comments for the given post, but if the user visits the same route the next time, it will just fetch the records from the store-cache. post.comments首先将导致Ajax调用,以获取给定帖子的所有评论,但是如果用户下次访问相同的路线,则只会从商店缓存中获取记录。

The problem is: What if another user added a comment to this post? 问题是:如果其他用户对此帖子添加评论怎么办? How to tell ember it has to reload its cache because something changed? 如何告诉ember由于发生了某些更改,它必须重新加载其缓存?

I already thought about a solution using websockets to tell clients which stuff to reload - but I don't think this is best-practice. 我已经考虑过使用websockets告诉客户要重新加载哪些内容的解决方案-但我认为这不是最佳实践。 And in addition, I can't imagine this isn't a common problem, so I am wondering what other developers are doing to solve this issue. 另外,我无法想象这不是一个普遍的问题,所以我想知道其他开发人员正在做什么来解决这个问题。

I tried to implement model updating in (experimental) chat application. 我试图在(实验)聊天应用程序中实现模型更新。 I have used SSE : ActionController::Live on server side (Ruby on Rails) and EventSource on client side. 我在服务器端使用了SSEActionController::Live (Ruby on Rails),在客户端使用了EventSource

Simplified code: 简化代码:

App.MessagesRoute = Ember.Route.extend({
  activate: function() {
    if (! this.eventSource) {
      this.eventSource = new EventSource('/messages/events');

      var self = this;
      this.eventSource.addEventListener('message', function(e) {
        var data = $.parseJSON(e.data);
        if (data.id != self.controllerFor('messages').get('savedId')) {
          self.store.createRecord('message', data);
        }
      });
    }
  }
});

App.MessagesController = Ember.ArrayController.extend({
  actions: {
    create: function() {
      var data = this.getProperties('body');
      var message = this.store.createRecord('message', data);
      var self = this;
      message.save().then(function (response) {
        self.set('savedId', response.id);
      });
    }
  }
});

The logic is simple: I'm getting each new record from EventSource. 逻辑很简单:我从EventSource获取每条新记录。 Then, if record was created by another client, the application detects it and new record being added to store using ember-data 's createRecord . 然后,如果记录是由另一个客户端创建的,则应用程序会检测到该记录,并使用ember-datacreateRecord将新记录添加到存储中。 Suppose this logic may have some caveats, but at least it serves well as 'proof of concept'. 假设此逻辑可能有一些警告,但至少它可以很好地用作“概念证明”。 Chat is working. 聊天正在进行。

Full sources available here: https://github.com/denispeplin/ember-chat/ 完整资源可在这里找到: https//github.com/denispeplin/ember-chat/

I have something to say about reloading: you probably don't want to perform full reloading, it's resource-consuming operation. 关于重新加载,我有话要说:您可能不想执行完全重新加载,这是耗资源的操作。 Still, your client side needs some way to know about new records. 尽管如此,您的客户端仍需要某种方式来了解新记录。 So, getting new records one-by-one via SSE is probably the best option. 因此,通过SSE一张一张地获取新记录可能是最好的选择。

If you just want to get rid of caching you can force a reload every time user navigates to comments route . 如果您只想摆脱缓存,则可以在用户每次导航到注释route时强制重新加载 But this largely depends on what you are trying to acheieve, I hope comments is just an example. 但这很大程度上取决于您要实现的目标,我希望comments只是一个例子。

If you want your ui to get updated automagically with changes in server, you need some communication with server, some polling mechanism like websocket or polling from a webworker . 如果您希望ui随服务器的更改自动更新,则需要与服务器进行一些通信,需要一些轮询机制,例如websocket或从webworker轮询。 Then you may reload the list of changed records sent from server. 然后,您可以reload从服务器发送的已更改记录的列表。 You are probably on the right track with this. 您可能正朝着正确的方向前进。

You can as well take a look at the orbitjs standalone library that integrates well with Ember. 您还可以查看与Ember很好集成的orbitjs独立库。 This is more useful if you require local storage as well and got to manage the multiple data sources. 如果您还需要本地存储并必须管理多个数据源,则此功能将更为有用。

This is really a common problem with any web application, no matter what framework you are using. 无论您使用什么框架,这实际上都是任何Web应用程序都常见的问题。 From my point of view, there are two main options. 从我的角度来看,有两个主要选项。 One: You have a service that polls the server to check to see if there are any changes that would require you to reload some of your models, have that service return those model IDs and refresh them. 一个:您有一项服务可轮询服务器以检查是否有任何更改需要您重新加载某些模型,让该服务返回这些模型ID并刷新它们,从而使该服务生效。 The other option is as you suggested, using a websocket and pushing notifications of model changes/new models themselves. 根据您的建议,另一个选项是使用网络套接字并推送模型更改/新模型本身的通知。

I would opt to actually just send the comment model itself, and push it into the Ember store and the associated post object. 我实际上选择仅发送评论模型本身,并将其推入Ember商店和关联的post对象。 This would reduce the need to hit the server with a hard refresh of your model. 这将减少对您的模型进行硬刷新的情况下访问服务器的需求。 I am currently using this method with my Ember app, where there is an object that contains overview data based on all the models in my app, and when a change is made in the backend, my websocket server pushes the new overview data to me application. 我目前在Ember应用程序中使用此方法,其中有一个对象包含基于我应用程序中所有模型的概述数据,并且在后端进行更改时,我的Websocket服务器将新的概述数据推送到我的应用程序中。

UPDATE:: I meant for this to be a comment, not an answer, oh well. 更新::我的意思是说这不是评论,而是好。

I've had this same issue with mobile app development. 我在移动应用程序开发中遇到了同样的问题。 While websockets seemed like the first answer, I was worried about scalability issues with limited server resources. 虽然websockets似乎是第一个答案,但我担心服务器资源有限的可伸缩性问题。 I decided to stick with the Ajax call to fetch newly modified records. 我决定坚持使用Ajax调用来获取新修改的记录。 This way server resources are only used if the user is active. 这样,仅当用户处于活动状态时才使用服务器资源。 However, as others pointed out, returning all comments every single time you need data makes your cacheing useless and is slow. 但是,正如其他人指出的那样,每次需要数据时都返回所有注释会使缓存变得无用且缓慢。 I suggest updating your rails server to accept an optional timestamp. 我建议更新您的Rails服务器以接受可选的时间戳。 If the timestamp is not supplied, then every comment is retrieved. 如果未提供时间戳,则将检索每个注释。 If a timestamp is supplied, then only return comments where the updated_at column is >= the supplied timestamp. 如果提供了时间戳,则仅返回updated_at>=提供的时间戳的注释。 This way, if no comments were added or modified since your last call, then you quickly get back an empty list and can move on. 这样,如果自上次通话以来未添加或修改任何注释,那么您会迅速返回一个空列表并继续前进。 If results are returned, you can then merge them with your existing list and show the updated comments. 如果返回结果,则可以将其与现有列表合并并显示更新的注释。

Example of fetching newly created or modified comments 获取新创建或修改的注释的示例

if params.has_key?(:updated_since)
  comments = Post.find(params[:id]).comments.where("updated_at >= ?", params[:updated_since])
else
  comments = Post.find(params[:id]).comments
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM