defer.promise returning same result in angularJS - angularjs

I have a Service which fetch the data from API.When I am trying to call this service. It's returning with same value.
appName.service('FetchCustomerDate', ['$http', '$q', function($http, $q) {
var self = this;
self.getCustomerData = function(token,name) {
var deferred = $q.defer();
return $http({
method: 'GET',
url: ,
headers: {
"Authorization": token,
"x-xcmc-auth": ''
}
}).then(function(response) {
deferred.resolve(response);
return deferred.promise;
}, function(response) {
deferred.reject(response);
return deferred.promise;
});
};
}]);

I see a bit of confusion here. Let's try to clear it. If you want to use deferred object, you need to change your code a bit:
appName.service('FetchCustomerDate', ['$http', '$q', function ($http, $q) {
var self = this;
self.getCustomerData = function (token, name) {
var deferred = $q.defer();
$http({ // Do not return here, you need to return the deferred.promise
method: 'GET',
url: '...some URL here...',
headers: {
"Authorization": token,
"x-xcmc-auth": ''
}
}).then(function (response) {
deferred.resolve(response); // It's correct, you are resolving the deferred promise here.
// return deferred.promise; // You do not need to return the deferred.promise here.
}, function (response) {
deferred.reject(response); // It's correct, you are rejecting the deferred promise here.
// return deferred.promise; // You do not need to return the deferred.promise here.
});
return deferred.promise; // The function must return the deferred.promise
};
}]);
In detail, function getCustomerData must return the promise belonging to deferred object with return deferred.promise. Inside then() callback you simply resolve or reject deferred promise. You do not need to return the deferred.promise.
You can improve the code. The $http service returns a promise, and the value returned by then callbacks is wrapped by then method in a promise. Knowing that, you can remove the use of deferred object:
appName.service('FetchCustomerDate', ['$http', function ($http) {
var self = this;
self.getCustomerData = function (token, name) {
return $http({ // Here, you need to return the promise returned by $http. Than promise will contain the response returned inside "then" callbacks.
method: 'GET',
url: '...some URL here...',
headers: {
"Authorization": token,
"x-xcmc-auth": ''
}
}).then(function (response) {
return response; // Simply return the response, it will be wrapped in a resolved promise by "then()"
}, function (response) {
return response; // Simply return the response, it will be wrapped in a rejected promise by "then()"
});
};
}]);
As you can see, the 2 then callbacks simply returns the response object, for this reason you can omit them:
appName.service('FetchCustomerDate', ['$http', function ($http) {
var self = this;
self.getCustomerData = function (token, name) {
return $http({ // Here, you need to return the promise returned by $http. Than promise will contain the response form the GET call
method: 'GET',
url: '...some URL here...',
headers: {
"Authorization": token,
"x-xcmc-auth": ''
}
});
};
}]);

Usually when you fetch data with the $httpservice, you want to obtain data from the response and affect it to the $scope for instance, or process it somehow. What are you trying to do? Please clarify your question.
Normally a fetch will look something like this:
appName.service('FetchCustomerDate', ['$http', '$q', function($http, $q) {
var self = this;
function notifyError(reason) {
console.error(reason);
}
self.getCustomerData = function(token,name) {
var deferred = $q.defer();
return $http({
method: 'GET',
url: ,
headers: {
"Authorization": token,
"x-xcmc-auth": ''
}
})
.then(function onSuccess(response) {
var cfg = response.data; // process data
})
.then(function onSuccess(response) {
// chained promises
})
.then(
function onSuccess(res) {
// ... this will trigger the chain reaction
deferred.resolve(res);
},
function onFailure(reason) {
notifyError(reason); // manage the error
deferred.reject(reason);
})
;
return deferred.promise;
}
}]);

Related

Ionic. Using $http giving error Cannot read property 'protocol' of undefined

This question is related to another one.
Before I did added $ionicPlatform, my service working just fine, but now there is something wrong with $http.
Here is example of injectables:
(function () {
"use strict";
angular.module('service', ['ionic'])
.service('BBNService', ["$http", "$localStorage", "$ionicPlatform",
function ($http, $localStorage, $ionicPlatform) {
And using of $http and $ionicPlatform
this.tips = function () {
var url;
$ionicPlatform.ready(function () {
if (window.Connection) {
if (navigator.connection.type == Connection.CELL_4G || navigator.connection.type == Connection.WIFI) {
if (this.getDayId = 0)//If Sunday - retrieve updated tips
url = this.host + "/tips/";
else
url = "data/tips.json";//If not - use saved data
}
}
});
var request = $http({
method: "GET",
url: url
}).then(
function mySucces(response) {
return response.data;
},
function myError(response) {
return response.data;
});
return request;
};
You need to send back the promise, doing a return response.data is not gonna work.
var deferred = $q.defer();
var request = $http({
method: "GET",
url: url
}).then(
function mySucces(response) {
deferred.resolve(response.data);
},
function myError(response) {
deferred.reject(response.data);
});
return deferred.promise;
And at the place where you consume this service:
BBNService.tips().then(
function(data) { //success call back with data },
function(data) { //error call back with data }
);
Please let me know if you need more explanation on using $q; always happy to give more details.

Return deferred.promise 2 services back

I have 3 services.
HttpSender - It controls the $http request
app.service("HttpSender", ["$http", "$q", function ($http, $q) {
this.send = function (path, method, params) {
var deferred = $q.defer();
$http({
url: path,
method: method,
params: params
}).then(function successCallback(response) {
deferred.resolve(response.data);
}, function errorCallback(response) {
deferred.reject(response);
});
return deferred.promise;
};
this.sendRequestWithFile = function (path, method, params) {
//todo check if needed
};
}]);
Api - controls all the api/ access token processes
service("API", ["HttpSender", "$q", 'WindowOpen', function(HttpSender, $q, WindowOpen){
var self = this;
var API = {};
API.requestTypes = {
GetMethod: "GET",
PostMethod: "POST",
DeleteMethod: "DELETE",
PutMethod: "PUT"
};
API.sendRequest = function (path, method, parameters, isCheckAccessToken)
{
path = ServersConfig.getApiServerUrl() + path;
parameters.access_token = getAccessToken();
HttpSender.send(path, method, parameters);
};
return API;
}]);
Api - Endpoint which activate the api request
app.factory('SelectedEndpoint', ['API',
function (API) {
var getPath = function (campaign) {
return "/campaigns/" + campaign.id + '/content/selected';
};
return {
get: function (campaign) {
API.sendRequest(getPath(campaign), API.requestTypes.GetMethod, {}, true).then(function (content) {
});
}
};
}]);
How can return the deferred.promise to the endpoint function so the then will get the answer? The following process only works if i add then also in the api factory the then return it to the endpoint
How can return the deferred.promise to the endpoint function so the then will get the answer?
By properly returning promises on each step.
1. HttpSender service. Do not use deferred here, just return promise directly:
app.service("HttpSender", ["$http", "$q", function($http, $q) {
this.send = function(path, method, params) {
return $http({
url: path,
method: method,
params: params
}).then(function successCallback(response) {
return response.data;
});
};
}]);
2. Api service. Make sure you return previous promise with return HttpSender.send(path, method, parameters);:
service("API", ["HttpSender", "$q", 'WindowOpen', function(HttpSender, $q, WindowOpen) {
var self = this;
var API = {};
API.requestTypes = {
GetMethod: "GET",
PostMethod: "POST",
DeleteMethod: "DELETE",
PutMethod: "PUT"
};
API.sendRequest = function(path, method, parameters, isCheckAccessToken) {
path = ServersConfig.getApiServerUrl() + path;
parameters.access_token = getAccessToken();
return HttpSender.send(path, method, parameters); // note return promise
};
return API;
}]);

How to do error handling when fetching data in angularjs service

This code fetches categories and give them to controller.
sampleApp.factory('SCService', function($http, $q) {
var SuperCategories = [];
var SCService = {};
SCService.GetSuperCategories = function() {
var req = {
method: 'POST',
url: SuperCategoryURL,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: "action=GET"
};
if ( SuperCategories.length == 0 ) {
return $http(req).then(function (response) {
SuperCategories = response.data;
return SuperCategories;
});
}else {
return $q.when(SuperCategories);
}
}
return SCService;
});
I think code is perfect until there is no error in http request.
My query is how to do error handling (try catch or something like that), in case if server have some issue or may be cgi-script have some issue and not able to server the request.
Angular promises use a method catch for that.
return $http(req).then(function (response) {
SuperCategories = response.data;
return SuperCategories;
}).catch(function(error) {
// Do what you want here
});
You should use also finally :
return $http(req).then(function (response) {
SuperCategories = response.data;
return SuperCategories;
}).catch(function(error) {
// Do what you want here
}).finally(function() {
// Always executed. Clean up variables, call a callback, etc...
});
Write like
return $http(req).then(function (response) {
//success callback
},
function(){
//Failure callback
});
Use callback methods from controller Like
Controller.js
service.GetSuperCategories(function (data) {console.log('success'},function (error){console.log('error'});
service.js
sampleApp.factory('SCService', function($http, $q) {
var SuperCategories = [];
var SCService = {};
SCService.GetSuperCategories = function(successMethod,errorMethod) {
var req = {
method: 'POST',
url: SuperCategoryURL,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: "action=GET"
};
return $http(req).then(successMethod(data),
errorMethod(error));
}
return SCService;
});
You can use the .success and .error methods of $http service, as below
$http(req).success(function(data, status, headers){
// success callback: Enters if status = 200
}).error(function(status, headers){
// error callback: enters otherwise
});

How can I make a $http call return a promise and data for $q?

I have the following script:
$q.all([
getActive(),
getUser()
])
.then(function (results) {
var x = results[0];
var y = results[1];
}
function getActive() {
$http({
url: '/api/Test/GetActive',
method: "GET"
})
};
function getUser() {
$http({
url: '/api/Test/GetUser',
method: "GET"
})
};
I was expecting to see that the variables x and y would contain the results of the $http calls but they both show as undefined.
Can someone suggest how I can make these calls return a promise. I actually thought $http did return a promise so I am confused.
You seem to be missing the return statement in both the getActive() and getUser() functions.
Try this:
$q.all([
getActive(),
getUser()
])
.then(function (results) {
var x = results[0];
var y = results[1];
}
function getActive() {
return $http({
url: '/api/Test/GetActive',
method: "GET"
});
};
function getUser() {
return $http({
url: '/api/Test/GetUser',
method: "GET"
});
};
Here's a working example. I changed your code in a few small ways. Note: The returned promises from the individual calls, the simplified way of calling $http, and pulling the data out of the returned results in the then() function:
http://plnkr.co/edit/YStkRt?p=info
function MainCtrl($scope, $q, $http) {
$q.all([
getActive(),
getUser()
])
.then(function (results) {
$scope.ip = results[0].data;
$scope.headers = results[1].data;
});
function getActive() {
return $http.get('http://ip.jsontest.com/');
}
function getUser() {
return $http.get('http://headers.jsontest.com/');
}
}

How can I pass back a promise from a service in AngularJS?

I have some code in my controller that was directly calling $http to get data.
Now I would like to move this into a service. Here is what I have so far:
My service:
angular.module('adminApp', [])
.factory('TestAccount', function ($http) {
var TestAccount = {};
TestAccount.get = function (applicationId, callback) {
$http({
method: 'GET',
url: '/api/TestAccounts/GetSelect',
params: { applicationId: applicationId }
}).success(function (result) {
callback(result);
});
};
return TestAccount;
});
Inside the controller:
TestAccount.get(3, function (data) {
$scope.testAccounts = data;
})
How can I change this so rather than passing the result of success back it
passes back a promise that I can check to see if it succeeded or failed?
Make your service to return a promise and expose it to service clients. Change your service like so:
angular.module('adminApp', [])
.factory('TestAccount', function ($http) {
var TestAccount = {};
TestAccount.get = function (applicationId) {
return $http({
method: 'GET',
url: '/api/TestAccounts/GetSelect',
params: { applicationId: applicationId }
});
};
return TestAccount;
});
so in a controller you can do:
TestAccount.get(3).then(function(result) {
$scope.testAccounts = result.data;
}, function (result) {
//error callback here...
});

Resources