AngularJS: POST 使用 $resource 更改服务器

AngularJS: POST changes to the server using $resource

我正在努力解决以下 AngularJS 问题。

我在服务器上的 .json 文件中有一个模型:

{
    feedback: []
}

我的目标是将用户生成的数据从表单推送到反馈数组,因此每个反馈评论都表示为一个 javascript 对象。

我尝试使用一项服务,该服务 returns 一个 angular $resource 指向我的 .json 中的反馈数组。实现如下(baseURL只是指向localhost上的一个端口):

.service('feedbackFactory', ['$resource', 'baseURL', function($resource, baseURL) {

    this.getFeedback = function() {

        return $resource(baseURL + 'feedback', null, {'update': {method: 'PUT'}});

    };

}])

然后我使用控制器按以下方式处理资源对象($scope.feedback是一个存储用户通过表单生成的数据的对象):

.controller('FeedbackController', ['$scope', 'feedbackFactory', function($scope, feedbackFactory) {

        $scope.sendFeedback = function() {

            if ($scope.feedback.agree && ($scope.feedback.mychannel === "")) {
                $scope.invalidChannelSelection = true;
                console.log('incorrect');
            }
            else {
                var feedbackData = feedbackFactory.getFeedback().query(
                    function(response) {
                        feedbackData = response;
                    }
                );
                feedbackData.push($scope.feedback);
                feedbackData.$save();
            }
        }
}])

不幸的是,我经常收到以下错误:feedbackData.$save is not a function。根据我目前阅读的所有内容,feedbackData 对象应该可以访问 $save 方法,但肯定有问题。我已经在这上面花了太多时间,所以我将非常感谢您的任何建议。

编辑。

经过一番努力,我尝试使用 feedback/:id 方法,所以我将服务更改为: .service('feedbackFactory', ['$resource', 'baseURL', function($resource, baseURL) {

    this.getFeedback = function() {

        return $resource(baseURL + 'feedback/:id', null, {'update': {method: 'PUT'}});

    };

}])

然后像这样将数据发送到服务器上的json:

var feedback = feedbackFactory.getFeedback().query(
                    function(response) {
                        feedback            = response;
                        $scope.feedback.id  = feedback.length;
                        feedbackFactory.getFeedback().save({id: $scope.feedback.id}, $scope.feedback);
                    }
                );

这次我当然得到了我实际预期的错误 - POST 无法完成,因为 json 中的数组是一个空数组,所以我无法解决它和任何它的不存在元素的数字索引。但是,我觉得这种方法无论如何都更好,而且我缺少一些简单但重要的东西。

我认为这可能有效

  else {
                var feedbackData = feedbackFactory.getFeedback().query(
                    function(response) {
                        feedbackData = response;
                        feedbackData.push($scope.feedback);
                        feedbackData.$save();
                    }
                );

            }

查询需要时间才能获取数据,因此可以安全地将变量分配给成功函数中的请求响应

在您的情况下,我认为它会在您 getFeedBack() 完成获取数据后开始读取下一行

$resource 用于 RESTful API。在您的情况下,RESTful API 可能是这样的:

  • 每个反馈都有一个 ID
  • /feedbacks returns 反馈数组
  • /feedbacks/:id returns 一个具体反馈
  • /feedbacks/new 和 POST 允许创建新反馈

query() 用于查询模型的所有实例(查询 /feedbacks),因此需要一个数组。 get()用于查询一个实例(通常是通过它的ID,在/feedbacks/:id上查询)。

在您的例子中,您没有将单个反馈视为模型对象,而是将整个反馈数组视为模型对象。

您的代码存在一些问题:

  • query() 需要一个实例数组,您的 API 只是 returns 一个实例对象。我不确定 query() 在这种情况下的行为(我猜它 returns 是一个空数组,因为你调用 push 没有错误消息)。
  • 如果它有效(在 API 返回数组的情况下),您不能对返回的变量调用 $save(),因为 $save() 是一个方法实例对象。 query() returns 个 数组 个实例。你想要的是使用 get().
  • 现在用get()代替query(),还是不行。因为 get() 的结果是异步的,所以你应该在回调中做所有事情。 get() returns a promise object,后面解析(当服务器回复AJAX请求时)。请在下面查看您的代码片段,评论它为什么不起作用。

    var feedbackData = feedbackFactory.getFeedback().get(
      function(response) {
            /* This will be executed later. Note 
               that affecting response to feedbackData is not necessary,
               since you already affected the result of .get(), which has 
               now resolved */
            feedbackData = response;
        }
    );
    /* feedbackData is just a promise, has not resolved into 
       instance object yet. $save() won't work */
    feedbackData.push($scope.feedback);
    feedbackData.$save();
    

现在正确的方法是:

var feedbackData = feedbackFactory.getFeedback().get(
    function() {
        /* Note that feedbackData is the object returned by your API,
           not directly the array inside the object */
        feedbackData.feedback.push($scope.feedback);
        feedbackData.$save();
    }
);

最后,$resource 是为 RESTful API 设计的。你的不是真的。我认为你最好直接使用 $http

好的,我终于找到了仍然使用 $resource 服务的问题的解决方案,所以我想这意味着它符合 CRUD 约束(解决方案基于这个很棒的博客 post: https://www.dunebook.com/introduction-to-resource-with-http-service-in-angularjs/#)

所以一切都非常简单。首先,我通过工厂设置我的资源:

.factory('feedbackFactory', ['$resource', 'baseURL', function($resource, baseURL) {

    return $resource(baseURL + 'feedback/:id', null, {'update': {method: 'PUT'}});

}])

然后我创建了一个新的 $resource 实例,我在其中填充了一个对象,其中包含我从用户生成它的 $scope 中获取的反馈信息。然后我 $save 把它放回原来的地方 ($save 代表我处理所有事情):

var newFeedback = new feedbackFactory($scope.feedback);
newFeedback.$save();

希望它能为某人省去几个小时的头痛。

解决方案是 POST 而不是 PUT。 POSTing 也会自动为新数据分配一个 id。我用了一个服务,但是一个工厂也可以。

.service('feedbackFactory', ['$resource', 'baseURL', function ($resource, baseURL) {
  this.getFeedback = function () {
    return $resource(baseURL + 'feedback/:id', null, {
      'save': {method: 'POST'}
    });
  };
}]);

然后控制器就这么简单

...
else {
  feedbackFactory.getFeedback().save($scope.feedback);
  ...
}

您不需要在 getFeedback 函数中包含“:id”,但包含它将允许您发出特定的 ID 请求(如果您愿意的话),就像在本课程中的 IndexController 中使用的那样。