AngularJS $http result with promise - javascript

I am new in angular $q service.I'm using $http with angular $q service for implementing asynchronous requests. Here in below is my codes which I can't get the result of backend api. (json)
Services.js :
.service('httpService', function($q, $http, $timeout) {
var asyncRequest = function(url) {
return $http.get(url)
.then(function(response) {
//res is the index of an array in php, which will be encoded.
return response.res;
}, function(response) {
// something went wrong
return $q.reject(response.res);
});
};
return {
asyncRequest : asyncRequest
};
});
Controller.js :
var result = httpService.test(url)
.then(function(data) {
// Line below gives me "undefined"
console.log(data);
}, function(error) {
alert("Error...!");
});
The mentioned line, gives me undefined. (Of course, I can write console.log(data) in main function, But it's not a good practice, because I want to return result to controller)
About my implementation of $q service, is there any easier way?
Any idea would be greatly appreciated.

You should not use $q in this instance, as $http already returns a promise. Using to 2 together in inefficient. ($q is of use if you are using a non-angular async function, such as a Geo lookup).
Services.js :
.service('httpService', function($http, $timeout) {
var asyncRequest = function(url) {
return $http.get(url)
};
return {
asyncRequest : asyncRequest
};
});
Controller.js :
var result = httpService.asyncRequest(url)
.then(function(res) {
console.log(res.data);
}, function(error) {
alert("Error...!");
});

First thing is that you are using factory style instead of service. service is just a function where methods are defined on this reference .
I think you don't need to use .then in service just return the promise returned by $http
app.service('httpService', function($q, $http, $timeout) {
this.asyncRequest = function(url) {
return $http.get(url);
};
});
And in controller
var result = httpService.test(url)
.then(function(res) {
// Line below gives me "undefined"
console.log(res.data);
}, function(error) {
alert("Error...!");
});

I think you are using the syntax for at factory on your service.
.service('httpService', function($q, $http, $timeout) {
this.asyncRequest = function(url) {};
});
or
.factory('httpService', function($q, $http, $timeout) {
return {asyncRequest: function(url) {}};
});

The response is already rejected in the mentioned line. You don't need to reject anything else. So you don't need to $q.
First you already return a promise. You can handle it in the controller with adding success() and error() delegates of the $http promise.
Second, this is async operation. And you can't return a response from the success callback like jQuery.ajax(). This is not synch call, this is asynch call and you have to use callbacks. Your mistake is here. Just return promise and handle it in controller when the response will has been resolved or rejected.
So your controller code can be like this:
httpService.asyncRequest({
...
}).success(function(successfulResponse) {
...
}).error(function(failedResponse) {
...
});

.service('httpService', function($q, $http, $timeout) {
var asyncRequest = function(url) {
var defer = $q.defer();
return $http.get(url)
.then(function(response) {
//res is the index of an array in php, which will be encoded.
defer.resolve(response);
}, function(response) {
// something went wrong
defer.reject(response.res);
});
return defer.promise;
};
return {
asyncRequest : asyncRequest
};
});
you should return promise from your object like this

Related

Angular Service working synchronously with Controller

I'm fairly new to AngularJS and have just begun to grasp many of the concepts I especially like the MVC design pattern. But I am having a difficult time implementing the Service layer in my application.
What I am finding is that after my Controller calls a method within the service, it continues with code execution before the service returns the data; so that by the time the service does return the data, it isn't of any use to the controller.
To give a better example of what I'm saying, here is the code:
var InsightApp = angular.module('InsightApp', ['chart.js']);
// Module declaration with factory containing the service
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function () {
return $http.get('Home/GetSalesData')
.then(function (result) {
return result.data;
});
}
};
});
InsightApp.controller("ChartSelectionController", GetAvailableCharts);
// 2nd Controller calls the Service
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections();
// This method is executed before the service returns the data
function workWithData(response){
// Do Something with Data
}
}
All the examples I've found seem to be constructed as I have here or some slight variation; so I am not certain what I should be doing to ensure asynchronous execution.
In the Javascript world, I'd move the service to the inside of the Controller to make certain it executes async; but I don't how to make that happen in Angular. Also, it would be counter intuitive against the angular injection to do that anyway.
So what is the proper way to do this?
http return a promise not the data, so in your factory your returning the $http promise and can use it like a promise with then, catch, finally method.
see: http://blog.ninja-squad.com/2015/05/28/angularjs-promises/
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections()
.then(function(res) {
// execute when you have the data
})
.catch(function(err) {
// execute if you have an error in your http call
});
EDIT pass params to model service:
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function (yourParameter) {
console.log(yourParameter);
return $http.get('Home/GetSalesData')
.then(function (result) {
return result.data;
});
}
};
});
and then :
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections('only pie one')
.then(function(res) {
// execute when you have the data
})
.catch(function(err) {
// execute if you have an error in your http call
});
You should proceed like this :
DataService.GetChartSelections().then(function (data) {
workWithData(data);
}
Actually $http.get returns a Promise. You can call the method then to handle the success or failure of your Promise
Should it not be like this, when your $http returns a promise or you pass a callback.
With passing callback as a param.
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function (workWithData) {
return $http.get('Home/GetSalesData')
.then(function (result) {
workWithData(result.data);
});
}
};
});
Controller code:
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections(workWithData);
// This method is executed before the service returns the data
function workWithData(response){
// Do Something with Data
}
}
Or use then or success:
var response = DataService.GetChartSelections().then(function(res){
//you have your response here... which you can pass to workWithData
});
Return the promise to the controller, dont resolve it in the factory
var InsightApp = angular.module('InsightApp', ['chart.js']);
// Module declaration with factory containing the service
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function () {
return $http.get('Home/GetSalesData');
}
};
});
In the controller,
var successCallBk =function (response){
// Do Something with Data
};
var errorCallBK =function (response){
// Error Module
};
var response = DataService.GetChartSelections().then(successCallBk,errorCallBK);

Service injection in controller AngularJs

Hello my code for service is:
angular.module('lucho1App').factory('ApiExample', ['$http', '$q', function($http, $q) {
return {
promiseToHaveData: function() {
return $http.get('http://data.colorado.gov/resource/4ykn-tg5h.json').then(function(response) {
var result = response.data;
console.log(result);
return result;
}, function(response) {
console.log('Error has ocurred');
});
}
};
}]);
and my controller is:
angular.module('lucho1App')
.controller('MainCtrl',['$scope', 'ApiExample',function MainCtrl($scope,ApiExample) {
$scope.apiExampl=ApiExample.promiseToHaveData();
console.log($scope.apiExampl);
}]);
the console.log in the service shows output which means that my request is successful but in the controller $scope.apiExampl is undefined where is my mistake?
A promise is asynchrnous, so it will be resolved later and the function in the then will be called at that very moment. The return in the callback permit to change the object passed to the next then call since promise are chainable object.
First you must return the promise object in your service :
return $http.get(...);
Second change your controller like this :
ApiExample.promiseToHaveData().then(function(data){
$scope.apiExampl=data;
});
note that here i do =data because in your service you already extracted the data object from the response
You need to return promise
promiseToHaveData: function() {
return $http.get('http://data.colorado.gov/resource/4ykn-tg5h.json');
}
And handle the success handler in controller
ApiExample.promiseToHaveData().success (function(response) {
$scope.apiExampl = response.data;
console.log($scope.apiExampl);
});

proper way to call http (RESTFUL WebAPI) in angularjs

I have following controller code
module.registerController('DemoCtrl', function ($scope, myFactory) {
myFactory.get(function (data) {
console.log(data); /// data is always undefined
});
});
and following the factory which is calling restful webapi
module.registerFactory('myFactory', ['$http',
function ($http) {
function get(callback) {
$http.get('mywebapiurl')
.success(function (response) {
//debugger; data comes back from server
callback(response);
}).error(function (response, status, headers, config) {
callback(response);
});
}
return {
get: get
}
}]);
The factory is calling webapi service and does gets the data back. However in controller the data doesnt get returned.
Am I missing something obvious here? Also not sure if this is the best way to call webservice in angularjs in controller using factory. Any inputs are most welcome.
Thanks,
You want to return a promise instead of passing a callback. As $http.get already returns a promise, you can just return that, or a derived promise that returns the response data directly. By the way, your factory looks like it should be a service instead:
angular.moudule('yourApp')
.service('myService', ['$http', myService]);
function myService($http) {
this.get = function(url) {
return $http.get(url)
.then(function transformData(response){
return response.data;
}).catch(function onError(rejectionResponse){
//Whatever you want to do here
});
}
}
This way myService.get will return a promise you can .then(), .catch() and .finally() on what you want, staying in the frameworks coding style. For example:
var squirrels = [];
myService.get('http://squirrelshop.com/api/squirrels')
.then(function(squirrelsData){
console.log('Got the squirrels!');
squirrels = squirrelsData;
}).catch(function(rejection){
console.warn('Couldnt fetch squirrels. Reason: ' + rejection);
});
controller code
module.registerController('DemoCtrl', function ($scope, myFactory) {
myFactory.get("url").then(function(d) {
console.log(d.data);
}
});
});
factory which is calling restful webapi
module.registerFactory('myFactory', ['$http',
function ($http) {
var apiFactory = {
get:function(url){
return $http.get(url);
}
}
return apiFactory;
}]);
Success and failure in factory
module.registerFactory('myFactory', ['$http',
function ($http) {
var apiFactory = {
get:function(url){
return $http.get(url).then(function(response){
// success
return responce.data;
},function(error){
//failure
return error;
};
}
}
return apiFactory;
}]);

How should I set data from an asynchronous service into a controller $scope?

All server data accesses in my page are performed by my RequestFactory provider.
(The RequestFactory uses $http to perform the actual server calls.)
My controller scope has a reference to the list of data returned from the RequestFactory.
My question is that since the RequestFactory calls are asynchronous, and the RequestFactory does not (and should not) have access to the controller scope, what is the proper way for the RequestFactory to hand off the data to the controller?
var requestFactory = {};
angular.module("myApp").factory("RequestFactory", function($http) {
requestFactory.fetch = function() {
$http.get(url).
success(function(data) {
controller.setData(data)
}).
error(function(data, status) {
console.info("fetch Failed. Error code: " + status + " Url:" + url);
}).finally(function() {
controller.setSubmitting(false);
});
};
return requestFactory;
});
You should return the promise from you factory. See below snippet.
.factory("RequestFactory", function($http) {
return {
fetch : function() {
return $http.get(url).then(function(result) {
return result.data;
});
}
}
});
In your controller you should use like
.controller('MainCtrl', function($scope, RequestFactory) {
RequestFactory.fetch().then(function(data)
$scope.foo = data;
});
});
You can do the following :
Service
(function(){
function Service($http){
function get(){
//We return a promise
return $http.get('path_to_url');
}
var factory = {
get: get
};
return factory;
}
angular
.module('app')
.factory('Request', Service);
})();
Controller
(function(){
function Controller($scope, $q, Request) {
var defer = $q.defer();
//Call our get method from the Request Factory
Request.get().then(function(response){
//When we get the response, resolve the data
defer.resolve(response.data);
});
//When the data is set, we can resolve the promise
defer.promise.then(function(data){
console.log(data);
});
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
As you know, $http service return promise, so after that, you can easily combining them.

How to view json data from angularjs http callback?

I can see my json data in the console and I want to view it on html page after clickbutton function. From my understaning I can either do a promise ($q) or then with http or ngResource. First I want to do http then migrate to ngResource. For some reason my scope is still undefined. Maybe it's a ng-init or ng-repeat I'm missing? Any ideas?
var app = angular.module('myApp', []);
app.factory('httpq', function($http, $q) {
return {
get: function() {
var deferred = $q.defer();
$http.get.apply(null, arguments)
.success(deferred.resolve)
.error(deferred.resolve);
return deferred.promise;
}
}
});
app.controller('myController', function($scope, httpq) {
httpq.get('http://localhost:8080/states')
.then(function(data) {
$scope.returnedData = data;
})
$scope.clickButton = function() {
$scope.returnedData;
}
});
view
<div data-ng-controller="myController">
<button data-ng-click="clickButton()">Get Data From Server</button>
<p>JSON Data : {{returnedData}}</p>
</div>
Use Ajax call
Service:
var demoService = angular.module('demoService', [])
.service('myService',['$http', function($http) {
this.getdata = function(entity){
var promise = $http({
method : 'POST',
url : 'services/entity/add',
data : entity,
headers : {
'Content-Type' : 'application/json'
},
cache : false
}).then(function (response) {
return response;
});
return promise;
};
}]);
Controller :
var demoService = angular.module('demoService', [])
.controller('myctr',['$scope','myService',function($scope,myService){
myService.getdata().then(function(response){
//Success
},function(response){
//Error
});
}]);
now you can see your json in controller success
$http itself is a promise, no need to create a new promise. Just return the $http.get wihoit the success written there and right the sucess fn in the controller itself. So your code will look like this:
app.factory('httpq', function($http) {
return {
get: function() {
return $http.get.apply(null, arguments);
}
}
});
Your controller:
app.controller('myController', function($scope, httpq) {
httpq.get('http://localhost:8080/states').then(function(data) {
$scope.returnedData = data;
})
$scope.clickButton = function() {
$scope.returnedData;
}
});
use
$scope.returnedData=JSON.parse(data);
It will give you values in JSON format
I have not worked with promise. But your factory code seems to be ok.
In controller declare your object first.
If it's just object declare it as
$scope.returnedData = {};
If it's array, declare it as
$scope.returnedData = [];
The the object will not be undefined and changes will affect in HTML

Categories

Resources