我目前正在开发一个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.get({courseId:id})”的返回值相比,“return course。$ save()”的返回值是未定义的。这是“对象对象”。
我想要的是在完全执行保存操作时设置FlashMessage,而不是在此之前设置。
有关于此的任何想法吗?我的REST服务的响应是正确的。它返回保存的对象。
电贺 马克
答案 0 :(得分:42)
有两种略有不同的API,一种用于处理资源实例,另一种用于更好的单词 - 更通用的版本。使用$
的主要区别 - 前缀方法(get
vs $get
)
$
中的get
- 前缀方法。代理呼叫并直接返回承诺。
在资源获得实例化之前的AFAIK,您只能访问具有正常var promise = Resource.get().$promise;
promise.then(function(res) { console.log("success: ", res); });
promise.catch(function(res) { console.log("error: ", res); });
的资源。
$
使用instanciated资源,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") });
- 前缀方法可用:
{{1}}
答案 1 :(得分:3)
如果您查看resource上的角度文档,则会提及
重要的是要意识到调用$ resource对象方法 立即返回一个空引用(对象或数组取决于 IsArray的)。一旦数据从服务器返回现有数据 引用填充了实际数据。
这很可能意味着您对$ save的调用将返回空引用。此外,{1}在Angular 1.2之前的资源API上不可用,因为资源不是基于then
的。
您应该更改promise
方法调用以接受函数参数以获得成功,并在那里执行必要的操作。
答案 2 :(得分:1)
这适用于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);
});
};
答案 3 :(得分:0)
我在控制器中添加了一个方法,以便在资源执行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(...)
答案 4 :(得分:0)
这是一个迟到的回复,但您可以在$ save ...
上进行回调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");
});