最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS $resource in service function - Stack Overflow

programmeradmin0浏览0评论

I'm working in a team that is building an Android application using web technologies (angular.js, etc.) and Phonegap to turn the project into an Android application. We're fairly new to AngularJS and have run into a problem integrating services into our code. We are trying to do some basic server calls, which are working as regular code, but we are trying to make them a service so we don't duplicate this all over the place. We're using a Phonegap localStorage plugin to store the ID of a database object on the phone's HTML5 local storage.

Here is our code:

.service("contactServer", function($resource, $http, baseUrl) {
    // Initialize resource and modify methods s.t. create POSTS and save PUTS.
    this.post = function() {
        alert("Starting post");
        var item = {"name": model.userName, "position": model.position};
        alert("Creating resource");
        var serverResource = $resource(baseUrl,
            {create: {method: "POST"}, save: {method: "PUT"}});
        alert("Created resource");
        new serverResource.create(item).then(function(data, status, headers, config) {
            alert("id: " + data._id);
            window.localStorage.setItem("DBid", data._id);
        }, function(data, status, headers, config) {
            alert(JSON.stringify(['Error', data, status, headers, config]))
        })
    }

    this.put = function() {
        alert("Starting put");
        var item = {"name": model.userName, "position": model.position, "id": window.localStorage.getItem("DBid")};
        alert("Creating resource");
        var serverResource = $resource(baseUrl + "/:id", {id: "@id"},
            {create: {method: "POST"}, save: {method: "PUT"}});
        alert("Created resource");
        new serverResource(item).save().then(function(data, status, headers, config) {
            alert(JSON.stringify(['Success', data, status, headers, config]));
        }, function(data, status, headers, config) {
            alert(JSON.stringify(['Error', data, status, headers, config]));
        })
    }
})

baseUrl is a URL link to our database. We call the services here:

.run(function(contactServer) {
    document.addEventListener("deviceready", onDeviceReady, false);

    function onDeviceReady() {

        if (window.localStorage.getItem("DBid") == null) {
            alert("no DBid");
            contactServer.post();
        }
        else {
            alert("Retrieved stored DBid: " + window.localStorage.getItem("DBid"));
            contactServer.put();
        }

    }
})

deviceready is a Phonegap event that fires when the application has loaded on the user's phone. We want to call these services in several of our controllers, but also initially during this run function.

The code fires up to the "starting post" alert after being called in the run function, but then breaks. Are we using $resource wrong? (It is correctly listed as a dependency). Are we implementing the service wrong?

I'm working in a team that is building an Android application using web technologies (angular.js, etc.) and Phonegap to turn the project into an Android application. We're fairly new to AngularJS and have run into a problem integrating services into our code. We are trying to do some basic server calls, which are working as regular code, but we are trying to make them a service so we don't duplicate this all over the place. We're using a Phonegap localStorage plugin to store the ID of a database object on the phone's HTML5 local storage.

Here is our code:

.service("contactServer", function($resource, $http, baseUrl) {
    // Initialize resource and modify methods s.t. create POSTS and save PUTS.
    this.post = function() {
        alert("Starting post");
        var item = {"name": model.userName, "position": model.position};
        alert("Creating resource");
        var serverResource = $resource(baseUrl,
            {create: {method: "POST"}, save: {method: "PUT"}});
        alert("Created resource");
        new serverResource.create(item).then(function(data, status, headers, config) {
            alert("id: " + data._id);
            window.localStorage.setItem("DBid", data._id);
        }, function(data, status, headers, config) {
            alert(JSON.stringify(['Error', data, status, headers, config]))
        })
    }

    this.put = function() {
        alert("Starting put");
        var item = {"name": model.userName, "position": model.position, "id": window.localStorage.getItem("DBid")};
        alert("Creating resource");
        var serverResource = $resource(baseUrl + "/:id", {id: "@id"},
            {create: {method: "POST"}, save: {method: "PUT"}});
        alert("Created resource");
        new serverResource(item).save().then(function(data, status, headers, config) {
            alert(JSON.stringify(['Success', data, status, headers, config]));
        }, function(data, status, headers, config) {
            alert(JSON.stringify(['Error', data, status, headers, config]));
        })
    }
})

baseUrl is a URL link to our database. We call the services here:

.run(function(contactServer) {
    document.addEventListener("deviceready", onDeviceReady, false);

    function onDeviceReady() {

        if (window.localStorage.getItem("DBid") == null) {
            alert("no DBid");
            contactServer.post();
        }
        else {
            alert("Retrieved stored DBid: " + window.localStorage.getItem("DBid"));
            contactServer.put();
        }

    }
})

deviceready is a Phonegap event that fires when the application has loaded on the user's phone. We want to call these services in several of our controllers, but also initially during this run function.

The code fires up to the "starting post" alert after being called in the run function, but then breaks. Are we using $resource wrong? (It is correctly listed as a dependency). Are we implementing the service wrong?

Share Improve this question edited Oct 25, 2014 at 6:03 artis3n asked Oct 24, 2014 at 19:57 artis3nartis3n 8402 gold badges12 silver badges23 bronze badges 2
  • What is baseUrl ? is that another service ? I don't understand why you are creating 2 methods in this.post if you are only using one. I would suggest another approach, have you consider to create a factory and return a resource class ? The way this is now is creating instance each time you call each method – rahpuser Commented Nov 5, 2014 at 2:57
  • Too many redundant information in the question. I think, you are able to localize the bugs by yourself. Read documentation docs.angularjs/api/ngResource/service/$resource and format your code. – dizel3d Commented Nov 5, 2014 at 13:14
Add a ment  | 

4 Answers 4

Reset to default 2 +50

The problem you have is the definition of your method change this

var serverResource = $resource(baseUrl,
            {create: {method: "POST"}, save: {method: "PUT"}});

Into this:

var serverResource = $resource(baseUrl, {},
            {create: {method: "POST"}, save: {method: "PUT"}});

Take a look at the documentation

So as yours methods are non Get instances you should execute them like following:

new serverResource.$create(item).then(function(data, status, headers, config) {
            //content
        }, function(data, status, headers, config) {
            //error content
        })

The documentation says:

HTTP GET "class" actions: Resource.action([parameters], [success], [error])

non-GET "class" actions: Resource.action([parameters], postData, [success], [error])

non-GET instance actions: instance.$action([parameters], [success], [error])

I would encourage you to use console.log instead of alerts to debug your code, the alert could create some problems with the digest cycle.

Let me give you an alternative solution:

.factory('contactServer', ['$resource', function($resource){
    var baseUrl = 'testing/:id';
    var resource = $resource(baseUrl, {id: '@id'}, {update: {method: 'PUT'}});
    return resource;
}]);

and you would use it as:

.run(function(contactServer) {
    document.addEventListener("deviceready", onDeviceReady, false);

    function onDeviceReady() {

        if (window.localStorage.getItem("DBid") == null) {
            alert("no DBid");
            //item creation
            var instance = new contactServer(item);
            contactServer.$save(item).then(function(res){
                 window.localStorage.setItem("DBid", res._id);
            });
        }
        else {
            alert("Retrieved stored DBid: " + window.localStorage.getItem("DBid"));
            var id = //theId;
            var updateObject = //item update;
            var instance = new contactServer();
            contactServer.$update({id: id}, updateObject).then(function(res){
                console.log('object updated!');
            });
        }

    }
});

..or something like that. Hope this help.

Hope this helps you on the right way:

  var app = angular.module("app", ["ngResource"]);

  app.service("contactServer", function($resource, $http) {
      // Initialize resource and modify methods s.t. create POSTS and save PUTS.
      var baseUrl = "test";
      var model = {
        userName: "",
        position: ""
      }

      var serverResource = $resource(baseUrl + "/:id", {id: "@id"},
              {create: {method: "POST"}, save: {method: "PUT"}});

      this.post = function() {
          alert("Starting post");
          var item = {"name": model.userName, "position": model.position};
          serverResource.create(item).then(function(data, status, headers, config) {
              alert("id: " + data._id);
              window.localStorage.setItem("DBid", data._id);
          }, function(data, status, headers, config) {
              alert(JSON.stringify(['Error', data, status, headers, config]))
          })
      }

      this.put = function() {
          alert("Starting put");
          var item = {"name": model.userName, "position": model.position, "id": window.localStorage.getItem("DBid")};
          serverResource.save(item).then(function(data, status, headers, config) {
              alert(JSON.stringify(['Success', data, status, headers, config]));
          }, function(data, status, headers, config) {
              alert(JSON.stringify(['Error', data, status, headers, config]));
          })
      }
  });

  app.run(function(contactServer) {
      document.addEventListener("deviceready", onDeviceReady, false);

      function onDeviceReady() {

          if (window.localStorage.getItem("DBid") == null) {
              alert("no DBid");
              contactServer.post();
          }
          else {
              alert("Retrieved stored DBid: " + window.localStorage.getItem("DBid"));
              contactServer.put();
          }

      }

  });

To make it a bit better I would return serverResource object from the service contactServer and use the resource's save and create methods in the controllers and run block (also resolve promises there).

In short: you have to create the $resource only once with $resource() (outside service function declarations) and just use that in the functions. Also no need for new keyword, might be the thing that breaks this.

Don't you need to change

serverResource.create(item).then(function(data, status, headers, config) {...}

into

serverResource.create(item).$promise.then(function(data, status, headers, config) {...}
                            --------

see https://docs.angularjs/api/ngResource/service/$resource at the end of the "Credit card resource" example

Actually it's interesting question.

As workaround I would suggest you to use Restangular if you want to build reusable instance for making http queries. In this case it has some advantages: - It uses promise instead of returning empty object and filling it with new data. (it's actually behaviour of ngResource). Thus you can reuse your services in resolve sections. - You don't have to create one $resource object per request. - Support a lot of http methods.

Here is example:

angular.module('app').service('accountService'function(Restangular){

   var baseAccounts = Restangular.all('accounts');

   this.getAll = function(){
      return baseAccounts.getList();
   }

   this.getById = function(id){
       /accounts/profile/{id}
       return baseAccounts.one('profile',id)
   }

})

More information you can find here. https://github./mgonto/restangular#differences-with-resource

发布评论

评论列表(0)

  1. 暂无评论