我有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。
或者也许是其他方式来做到这一点?
答案 0 :(得分:2)
我看到了一些决定:
1)您是否应该在用户点击“更新”按钮后发送请求(就像您目前正在做的那样)?或者,如果您在用户更改事物时发送请求(使用ngChange
)?
2)如果按下(1)的按钮方法,你应该发送每个Thing的请求(就像你现在正在做的那样),或者你应该首先检查是否已经更新/新建了Thing前端。
3)你怎么能处理这样一个事实:有些东西是新创造的而其他东西只是更新了?多条路线?如果是,那么您如何知道将请求发送到哪条路由?同样的路线?怎么样?
对我而言,使用“更新”按钮的好处似乎是用户清楚它是如何工作的。通过点击“更新”(之后可能会看到一条flash消息),用户知道(并获得视觉反馈)Thing已经更新。
使用“更新”按钮的成本是可能会有不必要的请求。网络通信速度很慢,所以如果你有很多事情,那么为每件事做出请求可能会非常慢。
最终,这似乎是我对用户体验与速度的决定。这取决于具体情况和目标,但我个人倾向于“更新”按钮。
这里的权衡似乎是代码简单性和性能之间的关系。更简单的解决方案就是为每个Thing提出请求,无论它是否已被更新/新创建(对于以前存在但没有改变的Thing,不会造成任何伤害 - 它们根本不会被更改)
更复杂但更高效的方法是跟踪事物是否已更新/新创建。您可以向Thing's添加一个名为dirty
的标记以跟踪此情况。
dirty: true
的标记。dirty: false
(无论您是否要将dirty
属性存储在数据库中,或者只是将其附加到服务器/前端结束取决于你)。dirty
属性将设置为true
。然后,使用dirty
属性,您只能请求dirty
的事物:
$scope.things.forEach(function(thing) {
if (thing.dirty) {
// make request
}
});
正确的解决方案取决于您的具体情况,但我倾向于在代码简单性方面犯错误而不是性能。
如果您使用的是Mongoose,default behavior就是在创建的文档中添加_id
字段(它也是default behavior,也可以是MongoDB本身)。因此,如果您没有覆盖此默认行为,并且如果您没有明确阻止将此_id
字段发送回客户端,则它应该存在于先前已创建的Thing中,从而允许您区分他们来自新创造的东西(因为新创造的东西不会有_id
字段)。
有了这个,您可以有条件地拨打create
或update
,如下:
$scope.things.forEach(function(thing) {
if (thing._id) {
Thing.update(thing._id, thing);
}
else {
Thing.create(thing);
}
});
或者,您可以使用单个路径为您执行“创建或更新”。您可以在{ upsert: true }
来电中设置update
来完成此操作。
在general中,upsert
将检查文档是否与查询条件匹配...如果匹配,则更新它,如果没有,则创建它。在您的情况下,您可以在Mongoose findByIdAndUpdate的上下文中使用upsert
,如下所示:
Thing.findByIdAndUpdate(id, newThing, { upsert: true }, function(err, doc) {
...
});
请参阅this SO post。
答案 1 :(得分:1)
首先,要回答是否有更新按钮的问题,你必须问自己。用户是否有理由放弃他的更改并且不保存他所做的工作。如果答案是否定的,那么我很清楚,不应该更新更新,这就是原因。
然后,您只需使用mongoDB查询中的upsert参数即可使用单个请求创建和更新您的内容。以下是控制器的外观。
$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
})
};