I have an angularjs factory like this:
'use strict';
angular.module('frontRplApp')
.factory('paymentService', function ($rootScope, $http, config, tools) {
var urlBase = config.baseUrl;
var paymentService = {
response: {},
create: function () {
var args = {};
return $http.post(urlBase + 'api/investor/payment/create', args);
}
});
And I intend to use it inside a controller like this (the important issue is being to do something different if all went well or if there was an error)
$scope.order = function () {
console.log('PaymentCashCtrl.order');
$scope.disabledButtons.submitCashOrder = true;
paymentService.create()
.then(
function (response) {
// do something with response
}, function (error) {
// do something with an error
}));
};
However my issue is that Id like to update some of the paymentService fields as the response of the $http.post is resolved and then return the promise so that the function(response) and function(error) callbacks in the controller keep working.
I tried with something like:
return $http.post(urlBase + 'api/investor/payment/create', args)
.then(function(response){
console.log(response);
this.response = response;
return response;
});
But it doesnt work since the function(error) handler in the controller is never called.
I want to use my handlers in the controller but also make some updates when the $http.post response is resolved.
Thanks.
in the factory, you need to return the functions paymentService object. also, don't resolve the promise inside the factory. resolve it in the controller.
.factory('paymentService', function($rootScope, $http, config, tools) {
var urlBase = config.baseUrl;
var paymentService = {
response: {},
create: function() {
var args = {};
return $http.post(urlBase + 'api/investor/payment/create', args);
}
}
return paymentService;
});
$scope.order = function() {
console.log('PaymentCashCtrl.order');
$scope.disabledButtons.submitCashOrder = true;
paymentService.create()
.then(
function(response) {
// do something with response
},
function(error) {
// do something with an error
}));
};
Use $q
Change your factory code to this:
angular.module('frontRplApp')
.factory('paymentService', function ($rootScope, $http, config, tools, $q) {
var urlBase = config.baseUrl;
var paymentService = {
response: {},
create: function () {
var deferred = $q.defer();
var args = {};
$http.post(urlBase + 'api/investor/payment/create', args)
.then(function(response){
console.log(response);
paymentService.response = response;
deferred.resolve(response);
}, function (error) {
deferred.reject(error);
});
return deferred.promise;
}
};
return paymentService;
});
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I have the following scenario, I need data from a particular url.I also need to save this datas into a variable that I can call everywhere in my controller. To overcome such issue, I have written a service like below :
app.service("userData", function ($http, $q) {
var deferred = $q.defer();
this.getUsers = function () {
return $http.get('/users')
.then(function (response) {
deferred.resolve(response.data);
return deferred.promise;
}, function (response) {
deferred.reject(response);
return deferred.promise;
})
;
};
});
And then my controller looks like :
app.controller('UserCtrl', function($scope, $q, userData) {
var myData = userData.getUsers()
.then(
function (result) {
$scope.users = result;
},
function (error) {
console.log(error.statusText);
}
);
console.log(myData)
});
It prints :
So how can i store data into a variable which is accessible all over the controller ?
Thanks..
I suggest you something like that:
angular.module("app").factory("userService", userService);
userService.$inject = ["$http", "$q"];
function userService($http, $q) {
var deferred = $q.defer();
var promise = null;
var currentUser = null;
return {
getUserInfo: function () {
if (promise) {
deferred.resolve(currentUser);
return (currentUser) ? deferred.promise : promise;
}
else {
promise = $http.get("http://swapi.co/api/people/1/").then(function (response) {
return currentUser = response.data.name;
});
return promise;
}
}
}
}
you can call then any time userService.getUserInfo() to get the cached data.
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl',
controllerAs: 'vc'
});
}])
.controller('View1Ctrl', function (userService) {
var vm = this;
userService.getUserInfo().then(function (result) {
vm.name = result
}, function (err) {
vm.name = err
});
});
I create a git repository to test it out: https://github.com/leader80/angular-cache-service
I hope it helps
I want to result of my $http.get from my service to my controller.
myserviceSample.js
function messagesService($q,$http){
var messages;
$http({
method: 'GET',
url: 'http://api.com/feedback/list'
})
.then(function success(response){
messages = response.data;
console.log(messages);
},function error(response){
console.log('error'+ response);
});
console.log(messages);
return {
loadAllItems : function() {
return $q.when(messages);
}
};
}
})();
mycontrollerSample.js
function MessagesController(messagesService) {
var vm = this;
vm.messages = [];
messagesService
.loadAllItems()
.then(function(messages) {
console.log(messages);
vm.messages = [].concat(messages);
});
}
})();
The above code results gives undefined output.
What i miss?
$q.when object does expect promise/object to make it working. In your case you have to pass promise object to $q.when as you are doing $http.get call. Here messages object doesn't hold promise of $http.get, so you could change the implementation of method like below.
Service
function messagesService($q,$http){
var messages = $http({
method: 'GET',
url: 'http://api.com/feedback/list'
})
.then(function success(response){
return response.data;
},function error(response){
return $q.reject('Error Occured.');
});
return {
loadAllItems : function() {
return $q.when(messages);
}
};
}
Then controller will resolve that promise & .then will do the trick
function MessagesController(messagesService) {
var vm = this;
vm.messages = [];
messagesService
.loadAllItems()
.then(function(messages) {
console.log(messages);
vm.messages = [].concat(messages);
});
}
Note: Using $q to create a custom promise, is considered as bad pattern when you have $http.get method there(which does return
promise itself)
Improved Implementation
function messagesService($q, $http) {
var messages, getList = function() {
return $http({
method: 'GET',
url: 'http://api.com/feedback/list'
})
.then(function success(response) {
messages = response.data
return response.data;
}, function error(response) {
return $q.reject('Error Occured.');
});
};
return {
loadAllItems: function() {
if (!data)
return getList(); //return promise
else
return $q.resolve(messages); //return data
}
};
};
No matter what I do I always get $$state or undefined back from my factory API call. I've tried promises and simply returning response.data from .then but nothing I tried works.
I can get the proper response data into my controller but then when I try to assign it to anything I just get undefined or $$state, depending on which method I use.
My factory:
factory('forecastFactory', function ($http, $q, SundialConfig) {
var Forecast = {};
var weatherKey = SundialConfig.openWeatherKey;
Forecast.dayCnt = 1;
Forecast.prepareCity = function (city) {
city === undefined ? city = 'Chicago, IL' : city = city;
return city;
}
Forecast.getForecast = function (city) {
var preparedCity = Forecast.prepareCity(city);
var deferred = $q.defer();
$http.jsonp('http://api.openweathermap.org/data/2.5/forecast/daily?', {
params: {
appid: weatherKey,
q: preparedCity,
cnt: Forecast.dayCnt,
callback: 'JSON_CALLBACK'
}
})
.then(function (res) {
console.log("success");
deferred.resolve(res);
})
.catch(function (err) {
console.log('error');
});
return deferred.promise;
}
return Forecast;
});
My controller:
controller('ForecastController', function ($scope, $location, forecastFactory, locationService) {
vm = this;
forecastFactory.getForecast('Chicago, IL').then(function (res) {
console.log(res);
vm.forecast = res;
});
});
I think you don't need to use $q because $http returns a promise,
you can do
Forecast.getForecast = function(city) {
var preparedCity = Forecast.prepareCity(city);
return $http.jsonp('http://api.openweathermap.org/data/2.5/forecast/daily?', {
params: {
appid: weatherKey,
q: preparedCity,
cnt: Forecast.dayCnt,
callback: 'JSON_CALLBACK'
}
})
.then(function(res) {
console.log("success");
return res.data;
})
.catch(function(err) {
console.log('error')
return []; // or {} depending upon required data
});
}
and in controller, do the same as you are doing now
Other way is simply return the promise returned by $http
Forecast.getForecast = function(city) {
var preparedCity = Forecast.prepareCity(city);
return $http.jsonp('http://api.openweathermap.org/data/2.5/forecast/daily?', {
params: {
appid: weatherKey,
q: preparedCity,
cnt: Forecast.dayCnt,
callback: 'JSON_CALLBACK'
}
})
}
and in controller do this
Sundial.Controllers.
controller('ForecastController', ['$scope', '$location', 'forecastFactory', 'locationService', function($scope, $location, forecastFactory, locationService) {
vm = this;
forecastFactory.getForecast('Chicago, IL').then(function(res) {
console.log(res)
vm.forecast = res.data;
}, function(err){
// do something
})
}]);
I have a REST call in service layer on which I have defined a promise which is making this asynchronous call a synchronous one and I am calling it from my controller method. Below is the code:
service method:
app.lazyload.factory('myService',['$http','$q', function($http,$q) {
return{
showAll :function ()
{
var deferred = $q.defer();
$http.post('rest/getAll?cd='+ (new Date()).getTime())
.success(function(data)
{
deferred.resolve(data);
})
.error(function(data)
{
deferred.reject(null);
console.log("in error block");
});
return deferred.promise;
}
};
}]);
controller method:
$scope.showAll = function()
{
var promise = myService.showAll();
promise.then(function success(data) {
$scope.allitems = data;
console.log(data);
console.log('$scope.allitems'+$scope.allitems[0].name);
$scope.showAllitems = true;
blockMyUI();
}, function error(msg) {
console.error(msg);
});
};
While debugging this javascript if I halt it for 2 sec i get the response but i don't get it if done non-stop. This means all REST call are working fine but there is some problem in my 'promise'. This promise is not waiting for REST call to complete which I want.
Try using $watch in controller.
var dataFromFactory = '';
myService.showAll().then( function(data){
dataFromFactory = data;
}
$scope.$watch(function () {
return dataFromFactory;
},
function (val) {
$scope.allitems = val;
console.log(val);
//the rest value you want.
}, false);
This question already has answers here:
How do I handle errors with promises?
(2 answers)
Closed 8 years ago.
I am using a provider to fetch some data via an API in my angular app and then use it in a controller. The API make call to is sometimes down which results in a 500 error. This error gets printed to the console and I don't know how to handle it gracefully.
Here is my provider code:
function myPvdr() {
this.getUrl = function() {
return 'http://path/to/my/API';
};
this.$get = function($q, $http) {
var self = this;
return {
getData: function(points) {
var d = $q.defer();
$http({
method: 'GET',
url: self.getUrl(),
cache: true
}).success(function(data) {
d.resolve(data);
}).error(function(err) {
d.reject(err);
});
return d.promise;
}
}
}
}
And here is how I use it in my controller:
function myCtrl($scope, myProvider, localStorageService) {
$scope.myData = localStorageService.get('data') || {};
myProvider.getData()
.then(function(data) {
localStorageService.set('data', data);
$scope.data = data;
});
}
How can I handle the 500 error properly, i.e. not throw any error to the console and use the data provided in local storage if any?
Many thanks
You can catch the reject of promise like this :
myProvider.getData()
.then(function(data) {
// promise resolved, data treatment
}, function(error) {
// promise rejected, display error message
});
or
myProvider.getData()
.then(function(data) {
// promise resolved, data treatment
})
.catch(function(error) {
// promise rejected, display error message
});
var app = angular.module('app', []);
function myProvider($http, $q) {
this.getUrl = function() {
return 'http://path/to/my/API';
};
this.getdata = function(points) {
var d = $q.defer();
$http({
method: 'GET',
url: this.getUrl(),
cache: true
}).then(function(data) {
d.resolve(data);
},function(err) {
d.reject(err);
});
return d.promise;
};
return this;
}
app.factory('myProvider', myProvider);
app.controller('firstCtrl', function($scope,myProvider){
// $scope.myData = localStorageService.get('data') || {};
getdata = function() {
myProvider.getdata()
.then(function(data) {
localStorageService.set('data', data);
$scope.data = data;
},
//handle error
function(e){
alert("Error " + e.status);
});
};
getdata();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app">
<div ng-controller="firstCtrl">
</div>
</body>