The AngularJS documentation has a Deprecation Notice for the $http success and error methods. Is there a specific reason this abstraction was removed from the library?
The problem was that .success and .error methods are not chainable because they ignore return values. This caused problems for people familiar with chaining and encouraged poor code from people unfamiliar with chaining. Witness all the examples on StackOverflow that use the deferred anti-pattern.
To quote one of the AngularJS team:
IMO .success and .error were a bad bit of API design in the first place. This issue highlights a number of situations where developers get confused because they either expect .success and .error to work the same way as .then or vice versa.
In a perfect world I would rather just ditch these $http specific "promises". Instead we could encourage developers to use the standard $q promise API .then and .catch. There is very little benefit IMO in working with explicit parameters over working with the response object.
— AngularJS Issue #10508 $http .success/.error dissimilar from how .then works.
Deprecation Notice (v1.5)
The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
— AngularJS $http Service API Reference -- deprecation notice
UPDATE
The deprecated .success and .error methods have been removed from AngularJS 1.6.
Due to b54a39, $http's deprecated custom callback methods - .success() and .error() - have been removed. You can use the standard .then()/.catch() promise methods instead, but note that the method signatures and return values are different.
$http(...)
.then(function onSuccess(response) {
// Handle success
var data = response.data;
var status = response.status;
var statusText = response.statusText;
var headers = response.headers;
var config = response.config;
...
}).catch(function onError(response) {
// Handle error
var data = response.data;
var status = response.status;
var statusText = response.statusText;
var headers = response.headers;
var config = response.config;
...
});
— AngularJS Developer Guide - Migrating to v1.6 - http
The pattern that javascript it using related to promises is only with .then(successCallback, errorCallback), so they are probably aiming to use js pattern.
Related
The AngularJS documentation has a Deprecation Notice for the $http success and error methods. Is there a specific reason this abstraction was removed from the library?
The problem was that .success and .error methods are not chainable because they ignore return values. This caused problems for people familiar with chaining and encouraged poor code from people unfamiliar with chaining. Witness all the examples on StackOverflow that use the deferred anti-pattern.
To quote one of the AngularJS team:
IMO .success and .error were a bad bit of API design in the first place. This issue highlights a number of situations where developers get confused because they either expect .success and .error to work the same way as .then or vice versa.
In a perfect world I would rather just ditch these $http specific "promises". Instead we could encourage developers to use the standard $q promise API .then and .catch. There is very little benefit IMO in working with explicit parameters over working with the response object.
— AngularJS Issue #10508 $http .success/.error dissimilar from how .then works.
Deprecation Notice (v1.5)
The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error.
— AngularJS $http Service API Reference -- deprecation notice
UPDATE
The deprecated .success and .error methods have been removed from AngularJS 1.6.
Due to b54a39, $http's deprecated custom callback methods - .success() and .error() - have been removed. You can use the standard .then()/.catch() promise methods instead, but note that the method signatures and return values are different.
$http(...)
.then(function onSuccess(response) {
// Handle success
var data = response.data;
var status = response.status;
var statusText = response.statusText;
var headers = response.headers;
var config = response.config;
...
}).catch(function onError(response) {
// Handle error
var data = response.data;
var status = response.status;
var statusText = response.statusText;
var headers = response.headers;
var config = response.config;
...
});
— AngularJS Developer Guide - Migrating to v1.6 - http
The pattern that javascript it using related to promises is only with .then(successCallback, errorCallback), so they are probably aiming to use js pattern.
I am trying to return an array of data inside a JSON object that is return from a URL, I can see the data that is being returned using console.log.
However when trying to catch the return array in a variable for example:
var arr = list();
console.log(arr.length);
The length being output by this code is "0" despite the fact that the data returned has content (so the length is greater than zero). How can I use the data?
list: function() {
var grades = [];
$.getJSON(
"https://api.mongolab.com/api/1/databases", function(data) {
console.log(data);
grades [0] = data[0].name;
console.log(grades.length);
});
return grades;
},
The issue you are facing is easy to get snagged on if you aren't used to the concept of asynchronous calls! Never fear, you'll get there.
What's happening is that when you call the AJAX, your code continues to process even though the request has not completed. This is because AJAX requests could take a long time (usually a few seconds) and if the browser had to sit and wait, the user would be staring in angsuish at a frozen screen.
So how do you use the result of your AJAX call?
Take a closer look at the getJSON documentation and you will see a few hints. Asynchronous functions like getJSON can be handled in two ways: Promises or Callbacks. They serve a very similar purpose because they are just two different ways to let you specify what to do once your AJAX is finished.
Callbacks let you pass in a function to getJSON. Your function will get called once the AJAX is finished. You're actually already using a callback in the example code you wrote, it's just that your callback is being defined inside of your list() method so it isn't very useful.
Promises let you pass in a function to the Promise returned by getJSON, which will get called once the AJAX is finished.
Since you are doing all this inside of a method, you have to decide which one you're going to support. You can either have your method take in callbacks (and pass them along) or you can have your method return the promise returned by getJSON. I suggest you do both!
Check it out:
var list = function(success) {
// Pass in the callback that was passed into this function. getJSON will call it when the data arrives.
var promise = $.getJSON("https://api.mongolab.com/api/1/databases", success)
// by returning the promise that getJSON provides, we allow the caller to specify the promise handlers
return promise;
}
// Using callbacks
list(function(grades) {
console.log(grades);
});
// Using promises
list()
.success(function(grades) {
console.log(grades);
});
I have done a service that gets a json file from the server with the translated values of the labels of my webapp. Seems to work fine:
mobilityApp.service('serveiTraduccions', function($resource) {
this.getTranslation = function($scope) {
var languageFilePath = 'traduccions/traduccio_en.json';
$resource(languageFilePath).get(function (data) {
$scope.translation = data;
});
};
});
What I am trying to do is acces that "$scope.translation" from my controler, I tried all and nothing worked. The object is saved in my $scope as you can see:
how can I get the values of the "registroBtnRegistro", "registroErrorRegistro" etc ?
Thanks in advance !
I tried:
console.log($scope.translation); -> undefined
console.log($scope['translation']); -> undefined
console.log($scope.translation.registroBtnRegistro); -> TypeError:
Cannot read property 'registroBtnRegistro' of undefined
console.log($scope.translation['registroBtnRegistro']); -> TypeError:
Cannot read property 'registroBtnRegistro' of undefined
Maybe you're trying to access these values from another $scope that not inherits the scope where you've created your translation model.
Try to assign this model directly to $rootScope, so you can access it from every scope:
mobilityApp.service('serveiTraduccions', function($resource, $rootScope) {
this.getTranslation = function() {
var languageFilePath = 'traduccions/traduccio_en.json';
$resource(languageFilePath).get(function (data) {
$rootScope.translation = data;
});
};
});
this answer is a blind attempt because your original post lacks basic information like the call from the controller.
we can refine it until we make it work.
First, you should be returning something from your method:
mobilityApp.service('serveiTraduccions', function($resource) {
this.getTranslation = function() {
var languageFilePath = 'traduccions/traduccio_en.json';
return $resource(languageFilePath);
};
});
You are using $resource but you might as well use basic $http.get(). at least it doesn't look like a restful api to me.
In any case, because it's an asynchronous request, it will not return the list of translated strings, but a resource "class" that allows methods like get, delete or the more general query():
from the docs: default methods are
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
sidenote: injecting $scope in a service doesn't make much sense to me: services are used to encapsulate common logic accross components. However, you can pass a scope instance as a parameter.
Then, the controller that uses this should have the service injected and use a callback to get the results when they have arrived (asynchronous operation!):
TraduccioCtrl ... {
$scope.translation = {}; // avoid undefined when the view just loads
ServeiTraduccions.getTranslation.query(function (response) {
$scope.translation = response; // and angular's two-way data binding will probably do the rest
});
}
The Angular docs about ng-resource have a working example. Other questions in SO have addressed this already too, like Using AngularJS $resource to get data
Hey guys I am trying to use an EPA API that provides daily UV Index information in JSON.
The link I am trying to read at the moment is:
http://iaspub.epa.gov/enviro/efservice/getEnvirofactsUVHOURLY/ZIP/33126/JSON?callback=callBackFn
If you open that link it shows valid JSON, but when I use it in my Angular.js code it does not read it, and my variable stays as unknown. My code is:
var tanApp = angular.module('tanApp')
.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
$scope.data = 'unknown';
$http.get('http://iaspub.epa.gov/enviro/efservice/getEnvirofactsUVHOURLY/ZIP/33126/JSON?callback=callBackFn').success(function(data){
$scope.data = data;
});
tanApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);
My HTML code is {{data}}.
When I take out the "JSON" portion, it comes up as XML, since it is the default, and that is actually showing up, but I need it as JSON.
Can someone possibly get this to work or provide some help? I can offer bitcoin as a bounty.
Thanks!
The problem is that the URI you're using returns raw JSON instead of JSONP. You can either setup a server-side proxy or check with your API provider to see if there's a way to get a valid JSONP response.
If you can get valid JSONP, you will also have to setup a callback to handle the response.
In that case, reference the accepted answer for this question.
Have you tried this using $http.jsonp() instead of $http.get(). Also if your using $http.jsonp() then the callback should be set to "JSON_CALLBACK".
e.g.
$http.jsonp('http://iaspub.epa.gov/enviro/efservice/getEnvirofactsUVHOURLY/ZIP/33126/JSON?callback=JSON_CALLBACK')
.success(function(data){
$scope.data = data;
}
I have a simple Backbone.js/Bootstrap front end in HTML5 with a Node.js/Restify backend. I am setting cookies in a header response from the server as below:
res.setHeader("Set-Cookie", ["token=ninja", "language=javascript"]);
On the client side, I am making a REST call as
var response = this.model.fetch().success(function(data){
//success
}).error(function(data){
//error
}).complete(function(data){
//complete
});
that callsback a parse method in the model.
How can I read the cookie value in the model?
Include Cookie.js.
You can then reference individual cookies like this:
var token = Cookie.get('token')
# token == 'ninja'
Here is what I figured out. My application has two components - the HTML/js from one domain that talks to a REST sevice on another domain (and therefore is cross-domain.) Because the cookie is set from REST, it appears is not readable across domains. So the web page will not store the cookie even though the server is sending it. One alternative is to use local cookies or use the technique illustrated by http://backbonetutorials.com/cross-domain-sessions/.
Assuming you are using jQuery with Backbone, you can get the headers by defining the parse function in your model by calling getAllResponseHeaders or getResponseHeader:
var model = Backbone.Model.extend({
// the rest of your model
parse: function(resp, xhr) {
var allHeaders = xhr. getAllResponseHeaders();
var cookieHeader = xhr. getResponseHeader("Set-Cookie");
// do something with the headers
return resp;
}
});