i am trying to consume this webservice (http://services.tvrage.com/feeds/show_list.php) from TVRage using Angularjs.
I can 'connect' to the service (using firebug I see GET show_list.php STATUS 200 OK) but when i try to print any data from the response I get none.
This is the code that i use:
var TV_Episodes = angular.module('TV_Episodes', ['ngResource']);
TV_Episodes.controller('GetAllEpisodes', function($scope, $resource) {
var dataService = $resource('http://services.tvrage.com/feeds/show_list.php');
$scope.data = dataService.get();
console.log($scope.data());
});
any ideas on how I can just console.log the the response?
UPDATE 1:
After some more trying i found out that that i get the following error as a response from TVRAGE.
"XMLHttpRequest cannot load http://services.tvrage.com/feeds/show_list.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access."
therefor i tweaked my code so
var dataService = $resource('http://services.tvrage.com/feeds/show_list.php?key=xxxx',{},{headers: { 'Access-Control-Allow-Origin': '*' }});
but i still get the same error as before.
$resource.get() returns a promise, which means you are likely printing to the console prior to the data being retrieved. Instead use the appropriate callback function:
$scope.data = dataService.get(function() { console.log($scope.data); });
The get method is asyncronous. When it is called it returns immediately with a reference to an object (or array, if specified - but not a promise as indicated in MWay's answer). Then, later, that same reference is updated with the data that is returned from the server on success. Here's the relevant part from the documentation:
It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data. This is a useful trick since usually the resource is assigned to a model which is then rendered by the view. Having an empty object results in no rendering, once the data arrives from the server then the object is populated with the data and the view automatically re-renders itself showing the new data. This means that in most cases one never has to write a callback function for the action methods.
As fast as the request might be, it won't resolve until the event loop comes around again. The resource is helpfully designed to free you up from having to worry about writing callbacks. If you need to though, the get method takes callback function parameters that will be invoked when the request resolves and the data is ready.
var TV_Episodes = angular.module('TV_Episodes', ['ngResource']);
TV_Episodes.controller('GetAllEpisodes', function($scope, $resource) {
var dataService = $resource('http://services.tvrage.com/feeds/show_list.php');
$scope.data = dataService.get(function () {
console.log($scope.data());
});
});
Or, you can access the promise used for processing the request by using *$promise", which is a property on empty instance object returned from get.
Related
I use a interval of 10 seconds for sending a request to get the most recent data:
var pollInterval = 10000;
var poll;
poll= $interval(function()
{
getNewestData();//$resource factory to get server data
}, pollInterval );
This works fine voor 99% of the time, but if the internet speed is really slow(I have actually experienced this), It will send the next request before the current is finished. Is there a way to just skip the current interval request if the previous one is still busy? Obsiously I could just use booleans to keep the state of the request, but I wonder if there is a better(native to angular) way of doing this?
Use the $resolved property of the Resource object to check if the previous operation is done.
From the Docs:
The Resource instances and collections have these additional properties:
$promise: the promise of the original server interaction that created this instance or collection.
$resolved: true after first server interaction is completed (either with success or rejection), false before that. Knowing if the Resource has been resolved is useful in data-binding.
$cancelRequest: If there is a cancellable, pending request related to the instance or collection, calling this method will abort the request.
-- AngularJS ngResource $resource API Reference.
How about making the request, then waiting for that to complete and then wait 10 seconds before making the same request again? Something along this line:
var pollInterval = 10000;
var getNewestData = function () {
// returns data in promise using $http, $resource or some other way
};
var getNewestDataContinuously = function () {
getNewestData().then(function (data) {
// do something with the data
$timeout(function () {
getNewestDataContinuously();
}, pollInterval);
});
};
getNewestData is the function that actually makes the request and returns the data in a promise.
And once data is fetched, a $timeout is started with timer as 10 seconds which then repeats the process.
I am using MEANJS
In my controller i have
// Find a list of Cars
$scope.findHome = function() {
$scope.cars = Cars.query();
console.log($scope.cars);
};
Which outputs
here i want to get the _id string inside the first array 0: Resource
I tried $scope.cars[0]._id which returns undefined, Please help.
You are inspecting the results of the query immediately after the call, but ngResource is asynchronous, so perhaps the data has not yet returned from the server by the time you are trying to access it. Try putting your access in the callback function passed to query().
$scope.cars = Cars.query(function() {
console.log($scope.cars);
console.log($scope.cars[0]._id);
});
I'm working with $resource in Angular 1.3.
I have a bunch of controllers with methods that work with the resource objects.
When the state of retrieval matters, these methods use the $promise property of the resource to ensure that they only process the objects after they are retrieved. These all work fine with existing and updated resource objects.
var ProposalResource = $resource(proposalUrl, {id: '#id'}, {'update': {method: 'PUT'}});
The resource objects are obtained by ProposalResource.get({id:....
However, when I create a new resource object in order to make a new object using new ProposalResource(..., the methods fail because the $promise property is undefined.
I've worked around this by setting the $promise property on the new resource object to a resolved promise.
This seems to work OK but it feels like a nasty kludge. The option of explicitly checking for whether or not the $promise property is defined in all the other methods is even less appealing though.
Am I doing the right thing?
I don't know why you need to use ProposalResource, but I usually use the $q provider.
That way you can do a simple function that returns a promise and you can call it from your controller methods.
Example service that uses a promise:
function someServiceMethod(params) {
//do something here, maybe create an object,maybe make a call with $http or something
var obj = createSomeObject(params);
//this resolves the object once the createSomeObject method or function have completed
$q.when(obj);
}
This approach is easier than doing the whole: var deferred = $q.defer(); and return deferred.promise after the deferred.resolves.
If you're using $resource, then I recommend just using $http provider from angular.
Here's $http
Here's $q
As mentioned in the $resource AngularJS Doucmentation:
Class actions return empty instance (with additional properties
below). Instance actions return promise of the action.
The statement above gives you a hint that instance action methods, $get, $save, ... and any other actions that you define in your $resource action definition, will always return a promise.
DEMO
e.g.
var User = $resource('user.json', {}, {
'update': {'method': 'PUT'}
});
var user = new User();
// this sends a GET request to user.json and returns the promise directly
// from the instance action.
user.$get()
.then(function(latestUserData) {
// latestUserData is also an instance of the User resource
return latestUserData.$update({
'name': 'Ryan'
});
})
.then(function(updatedUserData) {
// do whatever you want here
});
As you can see, the instance action $get returns a promise and when that promise is resolved, the .then() callback returns the response data from the server and at the same time it is wrapped/instantiated with the User $resource.
I have a data service in my application that is responsible for retrieving information for my controllers. This information might come from local storage, window or an ajax request. The problem I am facing is the $q promise responses don't look like $http responses.
this.getContactDetails = function(data) {
// The first time this method is called, we expect contact details to be preloaded on the page.
// We want to read and return that object then remove it from the page so subsequent requests are to the server.
if(typeof $window.preloadData.contact !== 'undefined') {
var contactDetails = JSON.parse(JSON.stringify($window.preloadData.contact));
delete $window.preloadData.contact;
// Since the method call should always have the same return type, we manually create a deferred object and set the resolution using the $q service.
var deferred = $q.defer();
deferred.resolve(contactDetails);
return deferred.promise;
}
var request = requests.contactDetails.get;
return $http(request);
};
The $q service does a nice job here but it resolves as the object it was given. I wouldn't really expect it to wrap the response. I know $httpBackend could accomplish this.
$httpBackend.whenGET(request).respond(contactDetails);
But the service is used in the MockE2E library and I doubt this was its intended use. I am not sure how to call this off afterwards or what would happen if I used it twice on the same request but I can figure out these questions. My other concern is that there doesn't seem to be a way to pass the same config object to $httpBackend as I do to $http. $httpBackend only accepts a method, url, body and headers, while $http config allows me to specify parameters.
Currently my work-around is simply to create and $http-like wrapper myself.
var contactDetails = JSON.parse(JSON.stringify({
data: $window.preloadData.contact
}));
But I don't find this very elegant. Is there a better/correct way to do this?
You can implement your storage layer as a $cacheFactory and add it to $httpProvider during the configuration phase.
From the docs:
When the cache is enabled, $http stores the response from the server in the specified cache. The next time the same request is made, the response is served from the cache without sending a request to the server.
Hence, if you provide your own implementation of a cache with the following methods:
{object} info() — Returns id, size, and options of cache.
{{*}} put({string} key, {*} value) — Puts a new key-value pair into the cache and returns it.
{{*}} get({string} key) — Returns cached value for key or undefined for cache miss.
{void} remove({string} key) — Removes a key-value pair from the cache.
{void} removeAll() — Removes all cached values.
{void} destroy() — Removes references to this cache from $cacheFactory.
You can return values read from localStorage, session cookies, etc. and they will be treated as there were data sent from the server, just without the AJAX request.
I have a service that returns JSON, assume this is the response:
{
"model": 48870,
"id": 20
}
I can do this:
$scope.response = Service.get();
And it will assign the JSON response to $scope.response. The issue here is I cannot directly access model or id via $scope.response.model or $scope.response.id, respectively. My workaround for this situation is to define a function in the service's success callback and fetch model or id from data. But this is not very practical considering $scope.response contains the entire JSON object and should in theory (and the sake of clean code) let me access its children.
Two questions here:
Is it a limitation of AngularJS representation of models?
How can I point to children (even grandchildren) without having to define a success callback for each call?
Once the asynchronous HTTP call returns, it is safe to access response's properties directly.
See this short example
app.controller('MainCtrl', function($scope, $resource) {
$scope.data = $resource('data.json').get(function() {
$scope.loaded = true;
//now it's safe to access $scope.data's properties:
$scope.data.foo = $scope.data.id + ':' + $scope.data.model;
});
});
UI bindings will work automatically.
I think what you are looking for is described here:
http://docs.angularjs.org/tutorial/step_05