I have multiple controllers that need to use my custom service which use $http. I did something like this
.service('getDB', function($http){
return {
fn: function(){
return $http({
url: "http://example.com",
method: "GET"
});
}
}
})
.controller('myCtrl', function($scope, getDB) {
console.log(getDB.fn());
}
In my console.log of getDB.fn() I see $promise, how can I get the response data?
$http returns a promise. Its implementation can be understood here :
$q
In order to use your promise, you have to do the following :
.controller('myCtrl', function($scope, getDB) {
getDB.fn(something).then(function(result){
// The result can be accessed here
}, function(error){
//If an error happened, you can handle it here
});
}
here is the way you can pass parameters :
.service('getDB', function($http){
return {
fn: function(something){
return $http({
url: "http://example.com/" + something,
method: "GET"
});
}
}
})
Related
I created a Service that obtain data with $http and this data is stored in a variable of this Service, also I created a Directive that use the service to create a tag select with options, these options were obtained in the service, but this is my problem the data obtained never connect with directive.
Service and Directive:
angular.module('myModule'[])
.factory('myService', ['$http', function($http){
var listOptions = [];
$http({
method: 'GET',
url: 'urlToDataJson'
}).then(function(resp){
listOptions = resp.data
})
;
return {
list: listOptions;
}
}]
.directive('myDirective', ['myService', function(myService){
restrict: 'E',
template: '<select ng-options="item.id as item.name for item in list"></select>',
replace: true,
controller: ['$scope', function($scope)
$scope.list = MyService.list;
]
}])
;
with the Chrome's DevTool I can see data is updated after $http runs, but the data not shown in the options.
The code above is an example that I need to do.
Your $http call returns a promise object. Wrap the $http call in a function and return the promise object, then, in your directive, invoke this function and resolve the promise object and get the data.
Specifically,
getData(){
return $http({
method: 'GET',
url: 'urlToDataJson'
}).then(function(resp){
listOptions = resp.data
); // this returns a promise
}
And then in your directive, resolve the promise like so:
MyService.getData().then(function(data){
console.log(data); // <-- this is how you access the result of your $http call
});
You can do this also ,
return $q(function (resolve, reject) {
$http({
method: 'GET',
url: 'urlToDataJson'
}).then(function(resp){
$scope.responseDate = resp.data;
resolve(responseData);
});
});
I got an error TypeError: Cannot read property 'success' of undefined when using $http and my custom service.
My app.js :
app.controller('AppCtrl', ['$scope', '$http', 'topicContent', function($scope, $http, topicContent){
topicContent.request().success(function(data){
$scope.threadContent = data;
console.log(data);
});
}]);
app.factory('topicContent', ['$http', function($http){
var query = function() {
return
$http({
url: "http://www.corsproxy.com/daysof.me/lowyat/thread.php",
method: "GET"
});
}
return {
request : function(){
return query();
}
}
}]);
This is so strange, I couldn't find any flaw of it.
The problem is that this code
var query = function() {
return
$http({
url: "http://www.corsproxy.com/daysof.me/lowyat/thread.php",
method: "GET"
});
}
is equivalent to this one:
var query = function() {
return;
$http({
url: "http://www.corsproxy.com/daysof.me/lowyat/thread.php",
method: "GET"
});
}
due to automatic semicolon insertion in javascript. Note that there is semicolon ; after return. So the solution is to move $http to the same line after return statement:
return $http({ ... });
Read about in what situations javascript interpreter inserts semicolon ; automatically, for example here. In your case after return interpreter will insert ; which makes query function return undefined. Hence the error you are getting.
I have a function getUsers that I want to return JSON from an web api .. but I cant seem to get the data out, I can't return the data because the function is inside $http. What should i do ?
function getUsers() {
$http({ method: 'GET', url: '/api/loginapi/userdetails' })
.success(function (data, status, headers, config) {
details = data;
});
return details;
}
$http makes an asynchronous call, so you can't immediately return fetched data.
What you can return is a promise. Good news, $http() returns one:
function getUsers() {
return $http({ method: 'GET', url: '/api/loginapi/userdetails' });
}
Then you can use your function:
getUsers().then(function(data) {
var details = data;
// Process your details!
});
You can access data there for sure, nothing is 'inside' $http, I suggest you pass in a callback to getUsers() and do whatever you want with the returned data:
var getUsers=function(callback){
$http({ method: 'GET', url: '/api/loginapi/userdetails' })
.success(function (data, status, headers, config) {
callback(data);
});
}
and use it like this inside your controller:
getUsers(function(users){
$scope.whatever = users;
})
I created plunkr for your question http://plnkr.co/edit/lqX4apmvnKM3i5jGZDQM?p=preview
$http return a promise. Please read details about promise at http://johnmunsch.com/2013/07/17/angularjs-services-and-promises/ . It is an important understanding if you want to write asynchronous application. This is another useful link - Inside my own Angular service, how do you get the return value back to the Controller that called the service? . Refer to answer. It explains how to use promise and deffered in angularjs.
var app = angular.module('plunker', []);
app.service('UserService', ['$http', '$q',
function($http, $q) {
this.getUser = function() {
return $http({
method: 'GET',
url: 'data.json'
});
};
}
]);
app.controller('MainCtrl', function($scope, UserService) {
$scope.user = {};
UserService.getUser().then(function(response){
$scope.user = response.data;
});
});
I'm trying to bind some data being returned from an API to my scope using promises with $q, I am able to pull the data from the server without any issue (I can see JSON being returned using fiddler) however the $scope variable remains empty, any help would be greatly appreciated! Thanks in advance.
Code:
toDoListService.js
app.factory("toDoListService", function ($http, $q) {
var deferred = $q.defer();
return {
get: function () {
$http({ method: 'GET', url: '/api/todo/' }).
success(function (data) {
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
deferred.reject(status);
});
return deferred.promise;
}
});
toDoListController.js
app.controller("toDoListController", function($scope, toDoListService){
$scope.toDoList = toDoListService.get();
});
First of all you should put var deferred = $q.defer(); in your get function, so that every get has it's own deferred object.
Second what get actually returns is a promise. So you need to access you data in this way:
app.controller("toDoListController", function($scope, toDoListService){
toDoListService.get().then(function(data){
$scope.toDoList = data;
});
});
Right now, your $scope.toDoList is bound to a promise. This means of binding used to work, but was deprecated in, I think, 1.2.
As Michael suggests, you must do:
app.controller("toDoListController", function($scope, toDoListService){
toDoListService.get().then(function(data){
$scope.toDoList = data;
});
});
Also, using $q is not required here at all, as $http returns a promise anyway. Therefore, you could just do:
app.factory("toDoListService", function ($http){
return {
get: function () {
return $http({ method: 'GET', url: '/api/todo/' });
}
};
});
You can simplify your code by using this:
toDoListService.js
app.factory("toDoListService", function ($http, $q) {
return {
get: function () {
return $http({ method: 'GET', url: '/api/todo/' });
}
}
});
toDoListController.js
app.controller("toDoListController", function($scope, toDoListService) {
toDoListService.get().then(function(response){
$scope.toDoList = response.data;
return response;
});
});
Be sure to return response in your success callback, otherwise chained promises would not receive it.
I have the following code in the controller.js,
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
return data
}).error(function(){
alert("error");
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = dataService.getData();
});
But, I think I m probably making a mistake with CORS related issue. Can you please point me to the correct way to make this call? Thanks much!
First, your success() handler just returns the data, but that's not returned to the caller of getData() since it's already in a callback. $http is an asynchronous call that returns a $promise, so you have to register a callback for when the data is available.
I'd recommend looking up Promises and the $q library in AngularJS since they're the best way to pass around asynchronous calls between services.
For simplicity, here's your same code re-written with a function callback provided by the calling controller:
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function(callbackFunc) {
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
// With the data succesfully returned, call our callback
callbackFunc(data);
}).error(function(){
alert("error");
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData(function(dataResponse) {
$scope.data = dataResponse;
});
});
Now, $http actually already returns a $promise, so this can be re-written:
var myApp = angular.module('myApp',[]);
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
// $http() returns a $promise that we can add handlers with .then()
return $http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
});
}
});
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(dataResponse) {
$scope.data = dataResponse;
});
});
Finally, there's better ways to configure the $http service to handle the headers for you using config() to setup the $httpProvider. Checkout the $http documentation for examples.
I suggest you use Promise
myApp.service('dataService', function($http,$q) {
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() {
deferred = $q.defer();
$http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
// With the data succesfully returned, we can resolve promise and we can access it in controller
deferred.resolve();
}).error(function(){
alert("error");
//let the function caller know the error
deferred.reject(error);
});
return deferred.promise;
}
});
so In your controller you can use the method
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(response) {
$scope.data = response;
});
});
promises are powerful feature of angularjs and it is convenient special if you want to avoid nesting callbacks.
No need to promise with $http, i use it just with two returns :
myApp.service('dataService', function($http) {
this.getData = function() {
return $http({
method: 'GET',
url: 'https://www.example.com/api/v1/page',
params: 'limit=10, sort_by=created:desc',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
}).success(function(data){
return data;
}).error(function(){
alert("error");
return null ;
});
}
});
In controller
myApp.controller('AngularJSCtrl', function($scope, dataService) {
$scope.data = null;
dataService.getData().then(function(response) {
$scope.data = response;
});
});
Try this
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);
Just setting useXDomain = true is not enough. AJAX request are also send with the X-Requested-With header, which indicate them as being AJAX. Removing the header is necessary, so the server is not rejecting the incoming request.
So you need to use what we call promise. Read how angular handles it here, https://docs.angularjs.org/api/ng/service/$q. Turns our $http support promises inherently so in your case we'll do something like this,
(function() {
"use strict";
var serviceCallJson = function($http) {
this.getCustomers = function() {
// http method anyways returns promise so you can catch it in calling function
return $http({
method : 'get',
url : '../viewersData/userPwdPair.json'
});
}
}
var validateIn = function (serviceCallJson, $q) {
this.called = function(username, password) {
var deferred = $q.defer();
serviceCallJson.getCustomers().then(
function( returnedData ) {
console.log(returnedData); // you should get output here this is a success handler
var i = 0;
angular.forEach(returnedData, function(value, key){
while (i < 10) {
if(value[i].username == username) {
if(value[i].password == password) {
alert("Logged In");
}
}
i = i + 1;
}
});
},
function() {
// this is error handler
}
);
return deferred.promise;
}
}
angular.module('assignment1App')
.service ('serviceCallJson', serviceCallJson)
angular.module('assignment1App')
.service ('validateIn', ['serviceCallJson', validateIn])
}())
Using Google Finance as an example to retrieve the ticker's last close price and the updated date & time. You may visit YouTiming.com for the run-time execution.
The service:
MyApp.service('getData',
[
'$http',
function($http) {
this.getQuote = function(ticker) {
var _url = 'https://www.google.com/finance/info?q=' + ticker;
return $http.get(_url); //Simply return the promise to the caller
};
}
]
);
The controller:
MyApp.controller('StockREST',
[
'$scope',
'getData', //<-- the service above
function($scope, getData) {
var getQuote = function(symbol) {
getData.getQuote(symbol)
.success(function(response, status, headers, config) {
var _data = response.substring(4, response.length);
var _json = JSON.parse(_data);
$scope.stockQuoteData = _json[0];
// ticker: $scope.stockQuoteData.t
// last price: $scope.stockQuoteData.l
// last updated time: $scope.stockQuoteData.ltt, such as "7:59PM EDT"
// last updated date & time: $scope.stockQuoteData.lt, such as "Sep 29, 7:59PM EDT"
})
.error(function(response, status, headers, config) {
console.log('### Error: in retrieving Google Finance stock quote, ticker = ' + symbol);
});
};
getQuote($scope.ticker.tick.name); //Initialize
$scope.getQuote = getQuote; //as defined above
}
]
);
The HTML:
<span>{{stockQuoteData.l}}, {{stockQuoteData.lt}}</span>
At the top of YouTiming.com home page, I have placed the notes for how to disable the CORS policy on Chrome and Safari.
When calling a promise defined in a service or in a factory make sure to use service as I could not get response from a promise defined in a factory. This is how I call a promise defined in a service.
myApp.service('serverOperations', function($http) {
this.get_data = function(user) {
return $http.post('http://localhost/serverOperations.php?action=get_data', user);
};
})
myApp.controller('loginCtrl', function($http, $q, serverOperations, user) {
serverOperations.get_data(user)
.then( function(response) {
console.log(response.data);
}
);
})