Подтвердить что ты не робот

Обещание по использованию ресурса 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 верен. Он возвращает сохраненный объект.

здоровается Марк

4b9b3361

Ответ 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");
});