Обещание по использованию ресурса AngularJS
В настоящее время я работаю над приложением REST + AngularJS.
У меня есть небольшая проблема относительно promises в действии сохранения ресурса.
Мой 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;
});
Мой контроллер:
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), все будет хорошо. Но возвращаемое значение "return course. $Save()" undefined, по сравнению с возвращаемым значением "return course.get({courseId: id}); который является" Объектом объекта".
Я хочу установить FlashMessage, когда действие сохранения было полностью выполнено, а не раньше.
Есть идеи по этому поводу? Ответ моей службы REST верен. Он возвращает сохраненный объект.
здоровается
Марк
Ответы
Ответ 1
Существует два немного разных API: один для работы с экземпляром ресурса и - при отсутствии лучших слов - более общая версия. Основное отличие заключается в использовании методов $
-prefixed (get
vs $get
)
Методы $
-prefixed в ngResource/resource.js. проксирует вызов и возвращает обещание напрямую.
AFAIK до того, как ресурс получит instanciated, вы можете получить доступ только к ресурсам с обычным get
.
var promise = Resource.get().$promise;
promise.then(function(res) { console.log("success: ", res); });
promise.catch(function(res) { console.log("error: ", res); });
С instanciated ресурсом доступны методы $
-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") });
Ответ 2
Если вы посмотрите на angular документацию на resource, она упоминает
Важно понимать, что вызов метода объекта ресурса $resource немедленно возвращает пустую ссылку (объект или массив в зависимости от IsArray). Как только данные будут возвращены с сервера, существующие ссылка заполнена фактическими данными.
Это вполне может означать, что ваш вызов $save вернет пустую ссылку. Кроме того, then
недоступен в ресурсе api до angular 1.2, поскольку ресурсы не основаны на 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
Это поздний ответ, но вы можете иметь callabck в $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");
});