web-dev-qa-db-ja.com

AngularJSリソース保存アクションの約束

現在、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

奇妙なことは、同じthen-callbackをファインダーの1つ(たとえば、findById)に追加すると、すべてが正常に機能することです。ただし、「return course.get({courseId:id});」の戻り値と比較して、「return course。$ save()」の戻り値は未定義です。これは「オブジェクトオブジェクト」です。

私が欲しいのは、保存アクションが完全に実行されたときにFlashMessageを設定することであり、その前ではありません。

これに関するアイデアはありますか? my REST=サービスからの応答は正しいです。保存されたオブジェクトを返します。

グリークマーク

19
mooonli

わずかに異なる2つのAPIがあります。1つはリソースインスタンスを操作するためのもので、もう1つはより適切な言葉がないため、より一般的なバージョンです。 $接頭辞付きメソッド(get vs $get)の使用の主な違い

ngResource/resource.js$-プレフィックスメソッド。呼び出しをプロキシし、promiseを直接返します。

リソースがインスタンス化される前は、通常のgetでのみリソースにアクセスできます。

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

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

インスタンス化されたリソースでは、$-接頭辞付きメソッドが利用可能です:

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

angular resource に関するドキュメントを見ると、

$ resourceオブジェクトメソッドを呼び出すと、すぐに空の参照(オブジェクトまたは配列はisArrayに依存)を返すことを理解することが重要です。サーバーからデータが返されると、既存の参照に実際のデータが入力されます。

これは、$ saveを呼び出すと空の参照が返されることを意味します。また、リソースAPIは、Angular 1.2より前ではリソースがthenベースではないため、promiseは使用できません。

saveCourseメソッド呼び出しを変更して、成功のための関数パラメーターを受け入れ、そこで必要なアクションを実行する必要があります。

3
Chandermani

これは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);
  });
};
1
HMR

これは応答が遅いですが、$ 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");
});
0
Samuel

コントローラーにメソッドを追加して、リソースが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(...)
0