平均/ AngularJS应用程序检查对象是否已经发布

我有thig angularJS前端,我在后端使用express,node和mongo。

我的情况如下所示:

//my data to push on server $scope.things = [{title:"title", other proprieties}, {title:"title", other proprieties}, {title:"title", other proprieties}] $scope.update = function() { $scope.things.forEach(function(t) { Thing.create({ title: t.title, //other values here }, function() { console.log('Thing added'); }) }) }; //where Thing.create its just an $http.post factory 

HTML部分看起来像:

 //html part <button ng-click="update()">Update Thing</button> 

然后在同一页上用户有能力改变$scope.things和我的问题是,当我再次调用update()所有的东西都发布两次,因为字面上多数民众赞成我在做什么。

有人可以解释我如何检查'东西'它已经发布到服务器只是为了更新值($ http.put),如果它没有在服务器上发布到$ http.post。

或者也许是其他方式来做到这一点?

我看到了一些决定:

1)在用户点击“更新”button之后是否应该发送请求(就像你现在正在做的那样)? 还是应该在用户更改Thing(使用ngChange )时发送请求?

2)如果按照(1)中的button方式进行操作,是否应该为每个事情发送一个请求(就像你现在正在做的那样),还是应该首先检查是否已经在前端更新/新build了Thing 。

3)如何处理一些事情是新创造的,而其他的只是简单的更新? 多条路线? 如果是这样,那么你怎么知道哪个路由发送请求? 同一条路线? 怎么样?


1

对我来说,使用“更新”button的好处似乎是,用户很清楚它是如何工作的。 通过点击“更新”(也许之后看到一个闪光消息),用户知道(并获得视觉反馈)Thing已被更新。

使用“更新”button的成本是可能有不必要的请求。 networking沟通很慢,所以如果你有很多事情的话,对每个事情的请求可能会很慢。

最终,这似乎是一个用户体验与速度的决定。 这取决于情况和目标,但我个人倾向于“更新”button。


2

这里的权衡似乎在代码简单性和性能之间。 更简单的解决办法就是对每一件事情提出请求,而不pipe是否已经更新/新创build(对于以前存在且没有改变的事情,不会造成任何损害 – 它们不会被改变) 。

更复杂但性能更高的方法是跟踪Thing是否已更新/新创build。 你可以添加一个叫做“ dirty的标志来logging这件事。

  • 当用户点击创build一个新的东西,新的东西将被给予一个dirty: true的标志dirty: true
  • 当你查询从数据库中获取所有东西的时候,它们都应该有dirty: false (不pipe你是否想将dirty属性存储在数据库中,还是简单地将它附加到服务器/前端都取决于你)。
  • 当用户改变现有的东西, dirty属性将被设置为true

然后,使用dirty财产,你只能提出的东西是dirty请求:

 $scope.things.forEach(function(thing) { if (thing.dirty) { // make request } }); 

正确的解决scheme取决于你的情况的具体情况,但我倾向于在代码简单性而不是性能方面犯错。


3

如果您使用的是Mongoose, 默认行为是为所创build的文档添加_id字段(这也是MongoDB本身的默认行为 )。 所以,如果你没有重写这个默认行为,并且你没有明确地阻止这个_id字段被发送回客户端,它应该存在于以前创build的Thing中,从而允许你将它们与新创build的事情(因为新创造的东西不会有_id字段)。

有了这个,你可以有条件地调用createupdate像这样:

 $scope.things.forEach(function(thing) { if (thing._id) { Thing.update(thing._id, thing); } else { Thing.create(thing); } }); 

或者,您可以使用一条执行“创build或更新”的路线。 你可以通过在update调用中设置{ upsert: true }来做到这一点。

通常 , upsert将检查文档是否与查询条件匹配。如果匹配,则更新它,如果不匹配,则创build它。 在你的情况下,你可以在Mongoose的findByIdAndUpdate上下文中使用upsert , 如下所示:

 Thing.findByIdAndUpdate(id, newThing, { upsert: true }, function(err, doc) { ... }); 

看到这个 SOpost。

@Adam Zemer整齐地处理了我在评论中提出的担忧,但是我有些观点不同意。

首先,要回答是否有更新button的问题,你必须问自己。 用户是否有理由放弃他的改变,而不是保存他所做的工作。 如果答案是否定的,那么很明显,更新不应该放在这里,这是为什么。

  1. 为了避免你的用户失去他的工作,你需要添加确认,如果他试图改变页面,或closures他的浏览器等。另一方面,如果一切都得到不断的保存,他安心,他的工作总是保存和你不必执行任何措施来防止他失去工作。
  2. 你减less了工作量,less一点点击任务可能看起来微不足道,但他可能多次点击它,一定要保存他的工作。 而且,如果它是一个经常性的任务,它肯定会改善他的经验。
  3. 性能明智,代码可读性明智,你做小的请求,而不必执行任何复杂的逻辑来做到这一点。 简单的改变input。
  4. 为了让他清楚,他的工作是不断保存的,你可以简单的说一个地方, 所有的变化都保存下来,并改变这个保存更改…当你提出请求。 例如,在网上看办公室或谷歌文档。

那么你所要做的就是在你的mongoDB查询中使用upsert参数,以便能够用一个请求来创build和更新你的东西。 这是你的控制器的外观。

 $scope.update = function(changedThing) { // Using the ng-change you send the thing itself in parammeter var $scope.saving = true; // To display the saving... message Thing.update({ // This service call your method that update with upsert title: changedThing.title, //other values here }).then( // If you made an http request, I suppose it returns a promise. function success() { $scope.saving = false; console.log('Thing added'); }, function error() { //handle errors }) };