AngularJS ngResource delete event not calling callback - angularjs

I have this code:
dogsResource.delete({id: $stateParams.dogId}, angular.noop,
function(value, responseHeaders){
//Success
console.log(value);
console.log(responseHeaders);
},
function(httpResponse){
//Error
console.log(httpResponse);
}
);
The delete is done, the problem is that neither success nor error is being called. I've also tried using an instance (that means, to use $delete), but it didnt work either.
I tried testing the callbacks with other methods, such as get
$scope.dog = dogsResource.get({id: $stateParams.dogId}, function(value, res){
console.log(value);
});
And it works. I don't know why that happen, since the dog is being deleted from database.
Thanks
UPDATE
dogResource code
// Return the dogs resource
.factory('dogsResource', ['$resource', function($resource){
return $resource("http://localhost:5000/dogs/:id",{id: "#id"},{update: {method: "PUT"}});
}])
UPDATE 2
I Found the error. It was in the RESTful API (Node js). The method was not sending anything to Angular, so no callback was triggered:
//DELETE - Delete a dog with specified ID
exports.deleteDog = function(req, res) {
console.log('DELETE' + req.params.id);
Dog.findById(req.params.id, function(err, dog) {
dog.remove(function(err) {
if(err) return res.status(500).send(err.message);
console.log('Succesfully deleted.');
res.status(200);
})
});
};
Replacing res.status(200) with res.status(200).end() got the callback triggered.
Thanks you all for your time.

I suggest to you to not use
res.status(200).end()
In fact usually when you delete an object with a REST service in expressJS, the common case is to send the deleted object as response, because it could be useful for the frontend to get this object (and to make sure that it's the good object).
So instead of use
res.status(200).end()
use
res.send(dog)
Or if you want to send an empty response, the status code for a delete operation should be :
res.status(204).end()
204 NO CONTENT
Note that you don't need to set the status code by default it will be 200. So set status code to 200 is just useless.
And to finish an http response needs to be sent to close the request. The end method or the send method make that. Set a status code to a response http will never send anything to the frontend. That's why your angular callback was never fired.
So i suggest to you to add the tag expressjs to your question, because it's not an AngularJS problem but a real expressJS mistake.

In your code, the second argument is angular.noop:
dogsResource.delete({id: $stateParams.dogId}, angular.noop,
function(value, responseHeaders){
//Success
console.log(value);
console.log(responseHeaders);
},
function(httpResponse){
//Error
console.log(httpResponse);
}
);
According to the ngResource Source Code, if you set the second argument to a function (angular.noop is a function) then it will use the second argument as the success callback. Since the second argument is a no-operation, nothing will happen when it is called.
Try setting the second argument to function (r) { console.log (r) } and see what you get.

I'm recently working with ngResource. In my case, I've have used three parameters in that api call. Therefore, you could use
dogsResource.delete({id: $stateParams.dogId}, function(value, responseHeaders){
//Success
console.log(value);
console.log(responseHeaders);
},
function(httpResponse){
//Error
console.log(httpResponse);
}
);
I hope that helps.

Use promise return by the $resource object. As $resource object by default return a promise object, and that promise object is available .$promise variable over that $resource API method.
Code
dogsResource.delete({id: $stateParams.dogId}).$promise.then(function(data)//Success
console.log(value);
},
function(httpResponse){ //Error
console.log(httpResponse);
});

Related

Node.js Express mssql - How to pass back data fetched from DB via promise chain

I am new to MEAN environment and not an expert in using promises. I am confused how to achieve this behaviour using promise.
my router method makes call to service method which has promise chained to qyery DB and returns results. I want to send back those results to router so I can send to front end. Thats there problem lies and I get undefined.
Router.js:
myrouter('/api/getDatafromDB',(req,res){
results =getSQLResults();
res.send(results); //want to achieve that.
}
SQLServiceFile.js :
//Db connection code defined in separate js file - dbConfig.js and
//imported in connection object
getSQLResults=function(){
connection.connect().then( //promise1
function(recordset){
request.query('select * from xyz') //promise 2
.then(
//recordset fetched fine here and want to pass to router.
rec= recordset['recordset']; //basically want to pass back rec.
console.log(rec);
connection.close();
).catch(function(err){
//error handling}
connection.close();)
}
).catch(//error handling code);
}
I tried different variations but did not work. Now I think somewhere I read that I need to pass back callback again in promise or something like that. I don't know. But I think If I change my code to use callbacks and not promise, it would work Or If I put back sql query code in router.
I want to keep code structured like this so please suggest right method.
Your code is syntactically wrong. Maybe the below piece of code will help you, it's the right way to use promises and async programming. The pattern used below is known as .then chaining. We can chain multiple .then to achieve a synchronous pattern in js.
.then and .catch only accept a function as an argument.
myrouter('/api/getDatafromDB', (req,res) => {
getSQLResults()
.then( result => res.send(results) )
.catch( err => ErrorHandler(err) )
}
SQLServiceFile.js :
//Db connection code defined in separate js file - dbConfig.js and
//imported in connection object
function getSQLResults() {
return connection.connect()
.then( function() {
return request.query('select * from xyz')
})
.then( function(recordset) {
connection.close();
return recordset['recordset'];
})
.catch( function(err) {
connection.close();
throw err; // it can be done so that you can handle the errors in myRouter
});
}

How is result passed from $http to the .onsuccess function?

How is result passed from the $http object to the unnamed function that is executed on success?
$http
.success(function (result) {
...
})
I know that the result is passed via any variable name that i put into the function. It is typically called result. But how is this done? It seems like wizardry to me.
I would expect to have to write something like:
$http
.success(function (result=$http.result) {
...
})
You have to study how both Javascript Function Paramters and Promises work.
The code that you pasted comes, I Think, from some AngularJS Application.
If my assumption is correct, $http is a service and doesn't have anyone success method.
The success method is present on $http methods:
//get, post, ecc...
$http.get(...).success()
By the way:
Javascript doesn't provide any way to match parameters, their order is always the order provided by the callee and the names that you use is just for you (Don't confuse with the IOC that the DependencyInjection in AngularJS does). EXAMPLE 1
function loggerCase1(log1, log2, log3, log4) {
console.log('loggerCase1 => param-1:', log1);
console.log('loggerCase1 => param-2:', log2);
console.log('loggerCase1 => param-3:', log3);
console.log('loggerCase1 => param-4:', log4);
console.log('---------------------');
};
function loggerCase2(log4, log2, log1, log3) {
console.log('loggerCase2 => param-1:', log4);
console.log('loggerCase2 => param-2:', log2);
console.log('loggerCase2 => param-3:', log1);
console.log('loggerCase2 => param-4:', log3);
console.log('---------------------');
};
function loggerCaseN() {
for(var i = 0; i < arguments.length; i++) {
console.log('loggerCaseN => param-' + (i + 1) + ': ', arguments[i]);
}
console.log('---------------------');
};
var logs = ['log1', 'log2', 'log3', 'log4'];
loggerCase1.apply(this, logs);
loggerCase2.apply(this, logs);
loggerCaseN.apply(this, logs);
If it's all clear about function parameters behaviour in javascript... you will know that isn't possibile to say give me the first as the second or something like that, also, the example that you pasted seems similar to default parameters (implemented in ES6, aka Javascript Harmony).
Let's go to the point 2:
In a simple promise chain (find on google or see the link above) you can pass a result to the next callback using return. EXAMPLE2
angular
.module('promisechainging', [])
.run(function($q) {
$q
.when('Hello World')
.then(function(greetings) {
console.log('ring 1', greetings);
return greetings;
})
.then(function(salut) {
console.log('ring 2', salut);
return salut;
})
.then(function(ciao) {
console.log('ring 3', ciao);
return { message: ciao };
})
.then(function(result) {
console.log('ring 4', result.message);
return result;
})
.catch(function(error) {
console.log('THIS LOG NEVER HAPPENS BECAUSE THERE AREN\'T REJECTED PROMISES');
return $q.reject(error);
})
.finally(function() {
console.log('We Are At The END');
})
;
})
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="promisechainging"></div>
Basically is not important how parameters are named!
Angular is using the promise mechanism which basically returns an object that let you know when the result is available or an error has been thrown.
When the ajax call returns, angular is calling the promise and providing the result as a parameter.
It's just like calling a regular function.
$http allows you to perform async network operations and returns a promise object (you can read more about promises in Angular here).
The success and error methods were used to declare callbacks to what happens when the promise is resolved (when the request was successfully completed) or rejected (when there was an error at processing the request). I used the past tense since they are now deprecated and the desired way to handle these is using the then method of the promise object.
// Simple GET request example:
$http({
method: 'GET',
url: '/someUrl'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Basically, the syntax is pretty much the same - the successCallbackFunction has the same signature as the method you were passing in the success method of your example.
But this is only the method signature. Your callback function parameters can be called however you want (result, data etc). All you have to keep in mind is that the first parameter in your callback function is going to be the data returned by your request.
$http
.success(function (result) {
...
})
$http will return a Promise Object which is nothing but a Javascript Object with success and different other functions.
So the statement immediately becomes like below as $http is evaluated,
(Promise Object)
.success(function (result) {
...
})
The success function of promise will save this anonymous function to be called once the promise is resolved. We can manually resolve promises, but I guess http will do this for you here.
Once http request(AJAX) is successful angular will tell this Promise object to run this success function by resolving the Promise, somewhat like:
suceess: function(responseData){ //success of AJAX
resolve(responseData); //this will pass the result to promise
}
Once resolve is called promise object has the result with it, it will then call the success function you passed initially with this value of result.
PS: This is a rough idea, I ave to look into Angular source to see their actual implementation.
Javascript functions are also class objects.
When $http completes it will call either the success or fail function - they are objects so they can be passed around. When it does, it will provide the parameters.

Angularjs analogue of jQuery .always()

I want to make a HTTP request to my server and can't find the answer on my question how to make .always() like in jQuery style.
According Angular's documentation of $http, there is only this construction:
// Simple GET request example :
$http.get('/someUrl').
then(function(response) {
// this callback will be called asynchronously
// when the response is available
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
There's the finally():
$http.get('/someUrl').
then(function(response) {
// this callback will be called asynchronously
// when the response is available
}.catch(error) {
// called asynchronously if an error occurs
// or server returns response with an error status.
}).finally() {
//Always do something
});
Which will always be called no matter what the outcome is.
You can read about this in the documentation for $q here.

Access to header information by $resource in AngularJS

I send a request server-side by $resource which is inside my factory.
In the return object there many information, but I'd like to have access to the authorization in the headers.
I tried to print the returning object by console.log() but I dont see any headers and authorization in console. What should I do?
controllers.controller('ProfileSettingCtrl', function ($scope,User) {
User.get({id: 'me'}, function(res) {
console.log(res);
$scope.profile = res;
})
Documentation for $resource
Success callback is called with (value, responseHeaders) arguments.
Seems like you can just get the headers with function (res, headers) { console.log(headers); }
According to the $resource docs, the header is passed as second argument to your success callback.
It's worth noting that the success callback for get, query and other methods gets passed in the response that came from the server as well as $http header getter function, so one could rewrite the above example and get access to http headers as:
var User = $resource('/user/:userId', {userId:'#id'});
User.get({userId:123}, function(u, getResponseHeaders){
u.abc = true;
u.$save(function(u, putResponseHeaders) {
//u => saved user object
//putResponseHeaders => $http header getter
});
});
If you want to use the header information, you have to use the success callback. Otherwise I always advice to use promises, which you can chain and pass around:
User.get().$promise.then(successCallback).catch(errorCallback);

Updating scope on form submit

I have a form that upon submit will POST a message to our REST API.
If successful, the REST API will return the updated value in the same JSON format as the GET call makes.
For some reason, even after the POST call has finished, the {{escalation.policy}} is still not updated in the scope.
var escalation = Escalation.save({
policy: $scope.policy,
}).$promise.then(function (data) {
$scope.escalation.push(data);
alert(data);
},
Is your REST request coming in then function? Try to put error function next to then() and make sure your request is successfully executed and responded back.
You need to call $scope.$apply() after $scope.escalation.push(data);. That will cause a new $digest to occur forcing the view to update, my guess is that $promise.then is ocurring outside the usual digest loop.
This is the current full segment of code for the submit()
$scope.submit = function () {
var Escalation = $resource('/api/escalation');
var escalation = Escalation.save({
policy: $scope.policy,
}).$promise.then(function (data) {
$scope.escalation.push(data);
}, function (error) {
alert('This request could not be processed. Please try again later.');
console.log(error);
});
};
The API will always return in the following format for a GET or POST:
{"policy":"Whatever the current/new policy is."}
Alas, i can still not seam to figure out why the view will not update.

Resources