4

I´m trying to create an angular function inside on Service to return acess data via $http and then return to a desired scope.

So my service it something like this;

app.service('agrService', function ($http) {

    this.testinho = function(){
        return "teste";
    }

    this.bannerSlides = function(){

        var dataUrl = "data/banner-rotator.json";

        // Simple GET request example :
        $http({
            method: 'GET',
            dataType: "json",
            url: dataUrl
        })
        .success( function(data, status, headers, config) {

            // this callback will be called asynchronously
            // when the response is available

            //console.log(data);
            return data;

        }).error( function(data, status, headers, config) {

            // called asynchronously if an error occurs
            // or server returns response with an error status.
            alert("Niente, Nada, Caput");
        });

    }

})

Then i want to associate the returned data to a scope inside of my main App controller... like this:

app.controller('AppCtrl', function($scope, $http, agrService) {
    $scope.slides = agrService.bannerSlides();
})

Then in my template i want to loop the data like this:

<div ng-repeat="slide in slides">
    <div class="box" style="background: url('{{ slide.url }}') no-repeat center;"></div>
</div>

The problem is that the data it´s only available on success and i don´t know how to pass it to my scope slides!!!!!

What i´m doing wrong?

Many thanks in advance

4 Answers 4

4

bannerSlides() doesn't return the values you need right away. It returns a promise that you can use to obtain the value at a later time.

In your service you can use the .then() method of the promise that $http() produces to do initial handling of the result:

 return $http({
    method: 'GET',
    dataType: "json",
    url: dataUrl
 }).then(function (data) {
     // inspect/modify the received data and pass it onward
     return data.data;
 }, function (error) {
     // inspect/modify the data and throw a new error or return data
     throw error;
 });

and then you can do this in your controller:

app.controller('AppCtrl', function($scope, $http, agrService) {
     agrService.bannerSlides().then(function (data) {
         $scope.slides = data;
     });
})
Sign up to request clarification or add additional context in comments.

8 Comments

Many thaks for your comment. I did exactly what you suggest, but now i´m having this error in my console: Resource interpreted as Image but transferred with MIME type text/html: "localhost:8100".
@Legues Hm, I think that might be something unrelated. I noticed that I changed your "json" datatype to "text" and forgot to change it back. Could you change that back to "json" and try again?
I´m almost there. but data entry in json it´s empty, and i guess it should have data that lives in my dataUrl. My data Json has the following values: [ { "id": 1, "url": "amendoeiraresort.com/assets/mobile/images/…" }, { "id": 2, "url": "amendoeiraresort.com/assets/mobile/images/…" }, { "id": 3, "url": "amendoeiraresort.com/assets/mobile/images/…" } ]
In my controller i hat to do this to entry in data entry: agrService.bannerSlides().then(function(data) { $scope.slides = data.data; }, function() { alert("error"); });
@Legues I see. Alternatively, you could have the then() callback in your service do return data.data;.
|
1

Use this in your service

.... 
this.bannerSlides = function(){
     var dataUrl = "data/banner-rotator.json";
     return $http({
        method: 'GET',
        dataType: "json",
        url: dataUrl
    });
};  
...

And this in your controller

agrService.bannerSlides().then(function(data) {
    $scope.slides = data;
}, function() {
   //error
});

you don't need $q promise inside the service because the $http is returning a promise by default

The $http service is a function which takes a single argument — a configuration object — that is
used to generate an HTTP request and returns a promise with two $http specific methods: success and error

reference

here is a Fiddle Demo

Comments

0

You need to return a promise and update your scope in the callback:

app.service('agrService', function ($q, $http) {

 this.bannerSlides = function(){
    var ret = $q.defer();
    var dataUrl = "data/banner-rotator.json";

    // Simple GET request example :
    $http({
        method: 'GET',
        dataType: "json",
        url: dataUrl
    })
    .success( function(data, status, headers, config) {

        // this callback will be called asynchronously
        // when the response is available

        ret.resolve(data);

    }).error( function(data, status, headers, config) {

        // called asynchronously if an error occurs
        // or server returns response with an error status.
        ret.reject("Niente, Nada, Caput");
    });
    return ret.promise;

 }
})

app.controller('AppCtrl', function($scope, $http, agrService) {
 $scope.slides = null;

 agrService.bannerSlides().then(function(data){
   $scope.slides = data;
 }, function(error){
   // do something else
 });

})

5 Comments

Your bannerSlides method has an unreachable return statement. And you don't really need that ret variable at all.
It depends where you want to format your answer, I removed the leftoverreturn $http thanks.
I'm not sure what you mean by that, but no, ret is completely unnecessary here because you already have a promise. $q.defer() is a mechanism for creating promises when you don't already have one to work with.
You could very well format your answer in the service rather than in the controller. Here for example we only resolve with the data, not the rest of the arguments.
You still don't need ret in order to format the answer in the service.
0

You can't return a regular variable from an async call because by the time this success block is excuted the function already finished it's iteration. You need to return a promise object (as a guide line, and preffered do it from a service).

Following angular's doc for $q and $http you can build yourself a template for async calls handling.

The template should be something like that:

angular.module('mymodule').factory('MyAsyncService', function($q, http) {

var service = {
    getData: function() {
        var params ={};
        var deferObject = $q.defer();
        params.nameId = 1;
        $http.get('/data', params).success(function(data) {
            deferObject.resolve(data)
        }).error(function(error) {
            deferObject.reject(error)
        });

        return $q.promise;
    }
}
});

angular.module('mymodule').controller('MyGettingNameCtrl', ['$scope', 'MyAsyncService', function ($scope, MyAsyncService) {

    $scope.getData= function() {
        MyAsyncService.getData().then(function(data) {
            //do something with data
        }, function(error) {
            //Error 
        })
    }
}]);

3 Comments

That getData method has about twice as much code as it needs (and a bug). You're using a very roundabout approach to achieve the equivalent of just returning $http.get('/data', params).
This because you don't want to handle you http results witin your controller, you jsut want to resolve your result when 100% sure its valid.
I would agree with that, except that's not what you're showing in your example. You're just passing the data and error along without inspecting them (and using an unnecessary defer object to do so).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.