Javascript MEAN/AngularJS应用程序检查对象是否已发布

Javascript MEAN/AngularJS应用程序检查对象是否已发布,javascript,angularjs,node.js,mongodb,express,Javascript,Angularjs,Node.js,Mongodb,Express,我有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.fo

我有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 part
<button ng-click="update()">Update Thing</button>
HTML部分如下所示:

//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 part
<button ng-click="update()">Update Thing</button>
//html部分
更新东西
然后,在同一页面上,用户可以更改
$scope.things
,我的问题是,当我再次调用
update()
时,所有内容都会被发布两次,因为实际上我就是这么做的

有人能告诉我如何检查“东西”是否已经发布到服务器上只是为了更新值($http.put),如果没有发布到服务器上则是$http.post


或者是另一种方法?

我认为需要做出一些决定:

1) 您是否应该在用户单击“更新”按钮后发送请求(就像您当前所做的那样)?或者,当用户更改内容时(使用
ngChange
),您是否应该发送请求

2) 如果使用(1)的按钮方法,您是应该为每件事发送请求(就像您当前正在做的),还是应该首先检查该事是否已在前端更新/新建

3) 你如何处理这样一个事实:一些东西是新创建的,而另一些只是更新而已?多条路线?如果是,那么您如何知道将请求发送到哪个路由?同一条路线?怎么做


1. 对我来说,使用“更新”按钮的好处在于用户很清楚它是如何工作的。通过点击“更新”(之后可能会看到一条闪光消息),用户知道(并获得视觉反馈)东西已经更新

使用“更新”按钮的代价是可能会有不必要的请求。网络通信很慢,所以如果你有很多东西,对每件东西都有一个请求可能会非常慢

最终,对我来说,这似乎是一个UX vs.速度的决定。这取决于形势和目标,但我个人倾向于“更新”按钮


2. 这里的权衡似乎是在代码简单性和性能之间。更简单的解决方案是,对每件事情都提出请求,不管它是否已更新/新创建(对于以前存在且未更改的事情,不会造成任何伤害-它们根本不会更改)

更复杂但性能更高的方法是跟踪某个对象是否已更新/新创建。你可以添加一个名为
dirty
的标志来跟踪这件事

  • 当用户单击创建新事物时,新事物将被赋予一个标记
    dirty:true
  • 当您查询以从数据库中获取所有内容时,它们都应该具有
    dirty:false
    (您是想将
    dirty
    属性存储在数据库中,还是仅仅将其附加到服务器/前端取决于您)
  • 当用户更改现有内容时,
    dirty
    属性将设置为
    true
然后,使用
dirty
属性,您只能对
dirty
对象发出请求:

$scope.things.forEach(function(thing) {
  if (thing.dirty) {
    // make request
  }
});
正确的解决方案取决于您的具体情况,但我倾向于在代码简单性而不是性能方面犯错误


3. 如果您使用的是Mongoose,则需要在创建的文档中添加一个
\u id
字段(它也是as MongoDB本身)。因此,如果您没有覆盖此默认行为,并且没有明确阻止将此
\u id
字段发送回客户机,那么它应该存在于先前创建的对象中,从而允许您将它们与新创建的对象区分开来(因为新创建的对象没有
\u id
字段)

这样,您可以有条件地调用
create
update
,如下所示:

$scope.things.forEach(function(thing) {
  if (thing._id) {
    Thing.update(thing._id, thing);
  }
  else {
    Thing.create(thing);
  }
});
Thing.findByIdAndUpdate(id, newThing, { upsert: true }, function(err, doc) {
  ...
});
或者,您可以使用为您执行“创建或更新”的单个路由。您可以通过在
update
调用中设置
{upsert:true}
来实现这一点

在中,
upsert
将检查文档是否与查询条件匹配。。。如果有匹配项,它会更新它,如果没有,它会创建它。在您的情况下,您可能会在猫鼬这样的环境中使用
upsert


见SO post。

@Adam Zemer巧妙地解决了我在评论中提出的问题,但我在一些问题上持不同意见

首先,要回答是否有更新按钮的问题,你必须问自己。用户是否有任何理由希望放弃所做的更改而不保存所做的工作。如果答案是否定的,那么我很清楚,更新不应该被放置,原因如下

  • 为了避免用户丢失其工作,如果用户试图更改页面或关闭浏览器等,则需要添加确认。另一方面,如果所有内容都持续保存,则用户可以放心,他的工作始终保存,您不必执行任何措施来防止他丢失工作
  • 你减少了他的工作量,对一项任务少点击一次似乎无关紧要,但他可能会多次点击以确保他的工作得到保存。此外,如果这是一项经常性的任务,肯定会提高他的经验
  • 就性能和代码可读性而言,您可以执行小请求,而不必实现任何复杂的逻辑。输入上的简单ng更改
  • 为了让他清楚地知道他的工作是持续保存的,你可以简单地说,你所有的更改都保存在某个地方,并将此更改为保存更改。。。当你提出请求时。例如,查看office online或谷歌文档
  • 然后,您需要做的就是在mongoDB查询中使用参数,以便能够通过单个请求创建和更新您的内容。以下是控制器的外观

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

    只是想澄清一下,当你第二次点击时,你想只更新一个arra吗