AngularJS Failed Resource GET - javascript

Does anyone know how you can check to see that a resource failed to be fetched in AngularJS?
For example:
//this is valid syntax
$scope.word = Word.get({ id : $routeParams.id },function() {
//this is valid, but won't be fired if the HTTP response is 404 or any other http-error code
});
//this is something along the lines of what I want to have
//(NOTE THAT THIS IS INVALID AND DOESN'T EXIST)
$scope.word = Word.get({ id : $routeParams.id },{
success : function() {
//good
},
failure : function() {
//404 or bad
}
});
Any ideas?

An additional callback function after your first callback function should fire when there is an error. Taken from the docs and group post:
$scope.word = Word.get({ id : $routeParams.id }, function() {
//good code
}, function(response) {
//404 or bad
if(response.status === 404) {
}
});
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])

Just to answer #Adio 's question too.
The second callback will be called when any http response code is considered to be an error by AngularJS (only response codes in [200, 300] are considered success codes). So you can have a general error handling function and don't care about the specific error.
The if statement there can be used to do different actions depending on the error code, but it's not mandatory.

This is just to inform.
From angular 1.6.x, success and failure is deprecated. So please now follow the then and catch on behalf of success and failure.
So, the above code look like in angular 1.6.x is as below:
$scope.word = Word.get({ id : $routeParams.id }).then(=> () {
//this is valid, but won't be fired if the HTTP response is 404 or any other http-error code
}).catch(=> () {
// error related code goes here
});

Related

Callback function on custom $resource action

I have added a custom action to a $resource:
var myResource = $resource('some/url/:someParam',
{
someParam: '#someParam'
},
{
update: {
method: 'PUT'
}
});
I am attempting to have a function run on completion. According to Angular's documentation, I'd do it in the following way:
non-GET "class" actions: Resource.action([parameters], postData, [success], [error])
Yet the following never invokes the success function even though the request is successful:
myResource.update({ someParam: 'a value' }, { myPostData: 'goes here' }, function(a,b) {
// this function never gets invoked
});
The documentation also says this:
The Resource instances and collections have these additional properties:
$promise: the promise of the original server interaction that created this instance or collection.
But this doesn't work either:
myResource.update({ someParam: 'a value' }, { myPostData: 'goes here' }).$promise.then(function() {
// do stuff
});
Am I missing something here? Any help would be greatly appreciated.

jquery is this a valid http request

I have this http request
GET /deals/couchbaseDocument/_search
{
"query" : {
"match" : {
"amenities" : "Maids "
}
}
}
when i put it in curl, it gives me results, i want to build a web app to call that request.
what i did is removing the newlines and put the whole text in .getjson()
as this:
var query = $("#query").val();
query = query.replace(/(\r\n|\n|\r)/gm,"");
$.getJSON(query, function (results) {
alert("success");
alert(results);
})
.success(function () { alert(" second success"); })
.error(function () {
alert("error");
alert(query);
});
i kept getting the error alert, i wonder if what i did is actually what should it be done to send that request
I read this
I found that .getJson could be like this:
$.getJSON('httpURL',
{ parameter1: "parameter value", parameter2: "parameter value" })
i wonder if i should pass my json request as a parameter
in case of the whole picture** i am working on sense elasticsearch plugin
According to the documentation of jQuery's getJson, you can pass a javascript object (jQuery.getJSON() | jQuery API Documentation) so you can do something like this
var queryData = {
"query" : {
"match" : {
"amenities" : "Maids "
}
}
};
$.getJSON('httpURL', queryData)

AngularJS code is giving back error?

$scope.logout = function () {
//var auth_token = $cookieStore.get('auth_token');
Auth.delete({
'auth_token': $cookieStore.get('auth_token')
}, function(data){
$scope.isLoggedIn = false;
$cookieStore.remove('auth_token');
});
When this called it given me an error:
Error: [$resource:badcfg] http://errors.angularjs.org/1.2.27/$resource/badcfg?p0=object&p1=array
z/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js:6:450
t/</f[d]/q<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular-resource.min.js:8:1
De/e/l.promise.then/J#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js:101:87
De/e/l.promise.then/J#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js:101:87
De/f/<.then/<#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js:102:259
Yd/this.$get</h.prototype.$eval#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js:113:28
Yd/this.$get</h.prototype.$digest#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js:110:109
Yd/this.$get</h.prototype.$apply#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js:113:360
m#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js:72:452
w#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js:77:463
ye/</B.onreadystatechange#http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js:79:24
http://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js
Line 92
Its a common problem. The delete method of resource model is expecting a json response which must be an object but your server is returning the json data in array format. So you have two options either change your server code to respond the json object data or change your resource model something like:
var Auth = $resource('/your-server-url', {}, {
delete: {
isArray: false
}
});
Hope this helps!
Thanks,
SA

angular-spinner | Skipping $http.post error handling

I am using angular-spinner to intercept all http request from my application and show a loading spinner.
Relevant code:-
//spinner configuration START
myApp.factory('spinnerInterceptor', ['usSpinnerService', function(usSpinnerService) {
return {
request: function(config) {
usSpinnerService.spin('spinner-1');
return config;
},
response:function(config){
usSpinnerService.stop('spinner-1');
return config;
},
responseError:function(config){
usSpinnerService.stop('spinner-1');
return config;
}
};
}]);
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('spinnerInterceptor');
}]);
//spinner configuration END
Except starting/stopping the spinner , I am simply just returning the config object.
Problem:-
One of my POST RESTful endpoint, return 404 status with an error message and still success handler of the $http block gets executed? Why?
$http({
method : 'POST',
url : url,
params :paramsJson,
data : _data
}).success(function(data,status) {
// THIS GET EXECUTED AFTER SPINNER INTERCEPTOR WITH STATUS 404 !!!!
}).error(function(data,status) {
// THIS BLOCK I EXPECT TO RUN IN CASE OF 404 or any non 2XX response
});
Before success/error handler of the $http, the spinnerInterceptor do get executed, which is somewhere playing with the error handling of the promise that gets returned.
When running my code without the spinner interceptor, everything works as expected.
Please help me fix this.
The problem here is "responseError" interceptor. you need to reject request in this block. else error is already handled in you interceptor so what ever you return here will go to success block.
The corrected interceptor code is:
responseError:function(config){//here we get response rename it
usSpinnerService.stop('spinner-1');
return $q.reject(config);
}
You can refer to Error Handling in angular for more info.
I had to develop an "automatic" spinner recently in a project. I used $q promises to signal success / error on the interceptor methods and it worked fine. My code was:
(function () {
'use strict';
function httpBusyInterceptor($q) {
function _responseError (response) {
//Hide spinner code
return $q.reject(response);
}
function _response (response) {
//Hide spinner code
return response || $q.when(response);
}
function _request (config) {
//Show spinner code
return config || $q.when(config);
}
return {
request: _request,
response: _response,
responseError: _responseError
};
}
httpBusyInterceptor.$inject = ['$q'];
angular.module('common.ui').factory('httpBusyInterceptor', httpBusyInterceptor);
})();

Backbone model.destroy() invoking error callback function even when it works fine?

I have a Backbone.js model that I'm trying to destroy when the user clicks a link in the model's view. The view is something like this (pseudocode because it's implemented in CoffeeScript which can be found at the bottom of the question).
var window.ListingSaveView = Backbone.View.extend({
events: {
'click a.delete': 'onDestroy'
},
onDestroy: function(event){
event.preventDefault();
this.model.destroy({
success: function(model, response){
console.log "Success";
},
error: function(model, response){
console.log "Error";
}
});
}
});
When I click the delete link in the browser, I always get Error logged to the console even though my server records successful destruction of the associated database record and returns a 200 response. When I refresh the page (causing the collection to re-render from the DB) the model I deleted will be gone.
One interesting this is that when I log the response in the error callback, it has statuscode 200 indicating success but it also reports statusText: "parseerror" whatever that means. There is no error in my server logs.
What am I doing wrong?
This is the response from the server:
Object
abort: function ( statusText ) {
always: function () {
complete: function () {
done: function () {
error: function () {
fail: function () {
getAllResponseHeaders: function () {
getResponseHeader: function ( key ) {
isRejected: function () {
isResolved: function () {
overrideMimeType: function ( type ) {
pipe: function ( fnDone, fnFail ) {
promise: function ( obj ) {
readyState: 4
responseText: " "
setRequestHeader: function ( name, value ) {
status: 200
statusCode: function ( map ) {
statusText: "parsererror"
success: function () {
then: function ( doneCallbacks, failCallbacks ) {
__proto__: Object
Here is the server action that destroy interacts with (Ruby on Rails)
# DELETE /team/listing_saves/1.json
def destroy
#save = current_user.team.listing_saves.find(params[:id])
#save.destroy
respond_to do |format|
format.json { head :ok }
end
end
And here is the actual CoffeeScript implementation of the Backbone View for people who prefer it like that:
class MoveOutOrg.Views.ListingSaveView extends Backbone.View
tagName: 'li'
className: 'listing_save'
template: JST['backbone/templates/listing_save']
events:
'click a.delete_saved': 'onDestroy'
initialize: ->
#model.bind 'change', this.render
render: =>
renderedContent = #template(#model.toJSON())
$(#el).html(renderedContent)
this
onDestroy: (event) ->
event.preventDefault() # stop the hash being added to the URL
console.log "Listing Destroyed"
#model.destroy
success: (model, response)->
console.log "Success"
console.log model
console.log response
error: (model, response) ->
console.log "Error"
console.log model # this is the ListingSave model
console.log response
#David Tuite comment:
"Ok I figured it out. It seems that Backbone expects the JSON response to be a JSON serialization of the record that was destroyed. However, Rails controller generators only return head :ok by default. I changed my JSON response to be render json: #listing_save where #listing_save is the record I just destroyed and it registers a success."
FYI - when you're doing a destroy, you don't need to return the full json for the destroyed model. you can return an empty json hash and it will work just fine. the only time you need to return the json for the model is on a save / update.
I had this same problem. In my delete method on the server (java), I didn't return anything. Just status 200/OK (or 204/No content). And so the "parsererror" problem was caused by jquery trying to convert the empty response into JSON, which failed (since "json" is the default data type).
My solution was to use the "text" dataType instead, which can be set in the options:
model.destroy({ dataType: "text", success: function(model, response) {
console.log("success");
}});
Your response must have status code 204 as you won't return any content. Since backbone uses a REST interface you should return different http status codes depending on the task.
Are you sure of your URL ? Do you append a .json at the end of the Backbone.Model url ? Since you check this on your server side (respond_to do |format| ... end), you might not send the correct head :ok response
Try with this destroy rails method to test if this is the problem :
def destroy
#save = current_user.team.listing_saves.find(params[:id])
#save.destroy
head :ok
end
Using the Slim Framework on an LAMP server you can add a Response Status to DELETE routes (or custom routes that don't return anything)
$app->response()->status(204);//204 No Content
this also sets the Content-Type back to text/html to allow for the empty body

Categories