Where did this pattern originate, using Two return statements with $http.post

19 views
Skip to first unread message

James Drinkard

unread,
Jul 28, 2017, 10:46:44 AM7/28/17
to Angular and AngularJS discussion
I recently had a requirement to create a custom component that would make a REST call to an API and then return data (a token) back. I'm working with Angularjs 1.4.2.  

So I created a custom directive that called a service to do this, however, I kept failing to return the data back to the directive.  All I would get was a promise back, except within the context of the $http.post code in the service and I was unable to get the value of the data from the promise.  

The solution was to have two return calls from $http.post.  My question is, where is this documented?  Maybe I'm just missing something here, but I spent a lot of time on this for a solution and this was the only one I could get to work.  I never could find this in the Angular docs, but I have missed some things before.  The solution came due to help from another dev who couldn't remember how they found this pattern.

Here is some of the code snippets:
//custom directive
$scope.login = function () {
var loginResponse = {};
var errorMessage = "";
var access_token = "";
loginService.login(myInfo).then(function(response) {
console.log("response is: " + JSON.stringify(response));
if(response.data.token) {
$window.sessionStorage.setItem("token", response.data.token);
}else{
errorMessage = response.data.errorMessage.split(":").pop();
console.log("errorMessage is: " + errorMessage);
... more code
//service
function loginService($window, $http, $httpParamSerializerJQLike) {
var service = {
login:login
};
return service;
 
function login(myInfo) {
... more code here
params = $httpParamSerializerJQLike(params);
console.log("The params are: " + params);
return $http({
 url: baseURL,
 method: 'POST',
 data:  params, 
 //Set the headers so Angular is passing information as form data, not request payload.
 headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function onSuccess(response) {
return response;    
}).catch(function onError(response) {
return response;
});
}

My questions are is this is a good pattern to use for this scenario and if not, what is better?  Again, I'd like to know who came up with the pattern and where it's documented?. 

Thank you, 
James

Sander Elias

unread,
Jul 28, 2017, 11:39:53 AM7/28/17
to Angular and AngularJS discussion
Hi James,

The pattern you describe is called Promises. They where in AngularJS before they arrived in JavaScript itself. They are a bit adapted in AngularJS to cater for the $digest loop. It's clearly stated that all $http calls return a promise. 

Straight from the documentation:
The $http API is based on the deferred/promise APIs exposed by the $q service. While for simple usage patterns this doesn't matter much, for advanced usage it is important to familiarize yourself with these APIs and the guarantees they provide.

That's on top of the $http docs page. 

Promises are a good pattern to use. In your case, I would move the 'unpacking' one to your service like this:
$scope.login = function() {
var loginResponse = {};
var errorMessage = '';
var access_token = '';

loginService
.login(myInfo)
.then(function(token) {
$window.sessionStorage.setItem('token', token);
access_token = token;
})
.catch(function(err) {
errorMessage = err.errorMessage.split(':').pop();
console.log('errorMessage is: ' + errorMessage);
});
};

//service
function loginService($window, $http, $httpParamSerializerJQLike) {
var service = {
login: login
};
return service;

function login(myInfo) {
params = $httpParamSerializerJQLike(params);

return $http({
url: baseURL,
method: 'POST',
data: params,
//Set the headers so Angular is passing information as form data, not request payload.
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function onSuccess(response) {
if (repsone.data.token) {
return response.data.token;
}
throw new Error('no token in response');
});
}
}


Also I noticed you use $scope a lot. That's discouraged by the core team for a long time already. If you want to know why, read the style-guide

James Drinkard

unread,
Jul 28, 2017, 12:27:12 PM7/28/17
to Angular and AngularJS discussion
Well I totally missed that!  Yes I knew a little about promises, but didn't see where having two return statements fit in.  In my code I'm returning the $http.post, (return $http) which it seems to be the promise object itself, and returning the response which contains the data in .the .then or.catch blocks).  I didn't see that documented in angular until I just now saw this: https://docs.angularjs.org/api/ng/service/$q.

Thank you,
James


Reply all
Reply to author
Forward
0 new messages