【问题标题】:Promise on AngularJS resource save action对 AngularJS 资源保存操作的承诺
【发布时间】:2017-11-07 09:08:53
【问题描述】:

我目前正在开发一个 REST + AngularJS 应用程序。

关于资源保存操作的承诺,我有一点问题。

我的工厂:

App.factory('Course', function($resource) {
    var course = $resource('/AppServer/admin/courses/:courseId', {}, {});

    course.findAll = function() {
        return course.query();
    };

    course.findById = function(id) {
        return course.get({
            courseId : id
        });

    };

    course.saveCourse = function(course) {
        return course.$save();
    }

    return course;
});

我的控制器:

App.controller('CourseEditController', function($scope, $routeParams, $location, Course, FlashMessage) {
    // load course into edit form
    $scope.course = Course.findById($routeParams.courseId);

    // save edited course and print flash message
    $scope.saveCourse = function() {
        var savedCourse = Course.saveCourse($scope.course);

        savedCourse.$then(function(httpResponse) {
            FlashMessage.set("Die Änderungen am Kurs <i>" + savedCourse.title + "</i> wurden erfolgreich gespeichert.");
            $location.path("/kurse/verwalten");
        });
    }
}); 

现在的问题是,我得到以下异常:

TypeError: Cannot call method '$then' of undefined

奇怪的是,如果我向其中一个查找器(例如 findById)添加相同的 then-callback,一切正常。但是“return course.$save()”的返回值是未定义的,与“return course.get({courseId:id});”的返回值相比这是“对象对象”。

我想要的是在保存操作完全执行时而不是在那之前设置 FlashMessage。

对此有什么想法吗?我的 REST 服务的响应是正确的。它返回保存的对象。

问候 马克

【问题讨论】:

  • 你说的是好课程.$save() 吗?有来自 $resource 的course 和来自参数的coursecourse.saveCourse = function(course)
  • 我正在调用参数中的那个。那是错的吗?或者另一个(从资源中)怎么知道要保存什么?
  • 嗨,这与问题完全无关,只是想知道您使用的是哪个 FlashMessage 库。即使状态发生变化,它也会闪烁警报消息吗?稍后将删除此评论。

标签: javascript html rest angularjs


【解决方案1】:

有两种稍有不同的 API,一种用于处理资源实例,另一种是更通用的版本。主要区别在于使用$-prefixed 方法(get vs $get

ngResource/resource.js 中以$ 为前缀的方法。代理调用并直接返回承诺。

AFAIK 在资源被实例化之前,您只能使用普通的get 访问资源。

var promise = Resource.get().$promise;

promise.then(function(res)  { console.log("success: ", res); });
promise.catch(function(res) { console.log("error: ", res); });

对于实例化资源,$-prefixed 方法可用:

var res = new Resource({foo: "bar"});

res.$save()
    .then(function(res)  { console.log("authenticated") })
    .catch(function(req) { console.log("error saving obj"); })
    .finally(function()  { console.log("always called") });

【讨论】:

  • 不确定我做错了什么,但是 save、$save、then 和 $then 的任何组合都不起作用并导致错误。我正在使用 1.0.8 你确定它应该这样工作吗?
  • Resource.$get()Resource.get().$promise 一样吗?
【解决方案2】:

如果您查看 resource 上的 Angular 文档,它会提到

重要的是要意识到调用 $resource 对象方法 立即返回一个空引用(对象或数组取决于 是数组)。一旦数据从服务器返回,现有的 参考是用实际数据填充的。

这很可能意味着您对 $save 的调用将返回空引用。此外 then 在 Angular 1.2 之前的 Resource api 上不可用,因为资源不是基于 promise 的。

您应该更改您的 saveCourse 方法调用以接受函数参数以获得成功并在那里执行必要的操作。

【讨论】:

    【解决方案3】:

    这适用于 Angularjs 1.0.8

    在我的服务中,我有以下几点:

    angular.module('dataProvider', []).
      factory('dataProvider', ['$resource','$q',function($resource,$q) { 
    //....
    var Student = $resource('/app/student/:studentid',
        {studentid:'@id'}
    );
        return {
          newStudent:function(student){
            var deferred = $q.defer();
            var s = new Student({name:student.name,age:parseInt(student.age)});
            s.$save(null,function(student){
                deferred.resolve(student);
            });
            return deferred.promise;
          }
        };
    }]);
    

    在我的控制器中:

    $scope.createStudent=function(){
      dataProvider.newStudent($scope.newStudent).then(
        function(data){
          $scope.students.push(data);
      });
    };
    

    【讨论】:

    【解决方案4】:

    我在控制器中添加了一个方法,以使资源在执行 CRUD 操作时具有承诺。

    方法如下:

    function doCrudOpWithPromise(resourceInstance, crudOpName){
                var def=$q.defer()
                resourceInstance['$'+crudOpName](function(res){def.resolve(res)}, function(err){def.reject(err)})
                return def.promise
    }
    

    一个调用示例是:

    var t=new MyResource()
    doCrudOpWithPromise(t,'save').then(...)
    

    【讨论】:

      【解决方案5】:

      这是一个迟到的回应,但你可以在 $save 上调用 callabck...

      var savedCourse = Course.saveCourse($scope.course);
      
      savedCourse.$save(function(savedCourse, putResponseHeaders) {
          FlashMessage.set("Die Änderungen am Kurs <i>" + savedCourse.title + "</i> wurden erfolgreich gespeichert.");
          $location.path("/kurse/verwalten");
      });
      

      【讨论】:

        猜你喜欢
        • 2013-10-29
        • 1970-01-01
        • 2018-01-09
        • 2015-07-09
        • 2014-06-15
        • 1970-01-01
        • 2016-08-25
        • 2015-12-06
        • 1970-01-01
        相关资源
        最近更新 更多