Html 对 AngularJS 资源保存操作的承诺

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17131643/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 10:09:29  来源:igfitidea点击:

Promise on AngularJS resource save action

javascripthtmlrestangularjs

提问by mooonli

I am currently working on a REST + AngularJS application.

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

I have a little problem concerning promises on resource save action.

关于资源节约行动的承诺,我有一个小问题。

My Factory:

我的工厂:

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

My Controller:

我的控制器:

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

Now the problem is, that I get the following exception:

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

TypeError: Cannot call method '$then' of undefined

The strange thing is that If I add the same then-callback to one of the finders (e.g. findById) everything works fine. But the return value of "return course.$save()" is undefined, compared to the return value of "return course.get({courseId:id});" which is "Object object".

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

What I want is to set the FlashMessage when the save action was fully executed and not before that.

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

Any ideas on this? The response from my REST service is correct. It returns the saved object.

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

Greets Marc

问候马克

回答by lafa

There is two slightly different API's, one for working with a resource instance and - in lack of better words - more generic version. The main difference beeing the use of $-prefixed methods (getvs $get)

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

The $-prefixed methods in ngResource/resource.js. proxies the call and returns the promise directly.

ngResource/resource.js 中$-prefixed 方法。代理调用并直接返回承诺。

AFAIK before the resource gets instanciated, you can only access resources with the normal get.

AFAIK 在资源被实例化之前,您只能使用正常的get.

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

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

With instanciated resource the $-prefixed methods are available:

使用实例化资源,$-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") });

回答by Chandermani

If you look at angular documentation on resourceit mentions

如果您查看有关资源的角度文档,它会提到

It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data.

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

This may very well means that your call to $save would return empty reference. Also thenis not available on Resource api before Angular 1.2 as resources are not promisebased.

这很可能意味着您对 $save 的调用将返回空引用。也then因为资源不是不可用之前角1.2资源APIpromise为主。

You should change your saveCoursemethod call to accept a function parameter for success and do the necessary action there.

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

回答by HMR

This is for Angularjs 1.0.8

这是用于 Angularjs 1.0.8

In my service I have the following:

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

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

In my controller:

在我的控制器中:

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

回答by Giovanni Bitliner

I added a method in controller to enable a resource have a promise when it executes a CRUD operation.

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

The method is the following:

方法如下:

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

An invocation example is:

一个调用示例是:

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

回答by Samuel

This is a late responde but you can have callabck on $save...

这是一个迟到的回应者,但您可以在 $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");
});