Trouble making a simple API call with Angular - javascript

Why is it that when I try to retrieve data with this simple API call I get an error that says http://127.0.0.1:8080/%7B%7Buser.avatar%7D%7D <- ? But if I move my promise into my controller it works. I thought that you can make your promises in your service and it'll work fine?
This is my controller.js file
angular.module('userProfiles').controller('MainController', function($scope, mainService) {
$scope.getUsers = function() {
mainService.getUsers();
}
$scope.getUsers();
});
This is my services.js file
angular.module('userProfiles').service('mainService', function($http) {
var baseUrl = 'http://reqres.in/api/users?page=1';
this.getUsers = function() {
return $http({
method: 'GET',
url: baseUrl
}).then(function(response) {
this.users = response.data.data;
});
}
});

You aren't assigning the response.data.data to anything usable outside that callback. Try it like this instead, returning a promise that resolves with the users data...
this.getUsers = function() {
return $http.get('http://reqres.in/api/users', {
params: {page: 1}
}).then(function(res) {
return res.data.data;
});
};
and in your controller
$scope.getUsers = function() {
mainService.getUsers().then(function(users) {
$scope.users = users;
});
};

Related

http post response is null

I'm sending http post request to REST api, I'm getting status ok response from server but in this script, it always runs 'myError' function. In backend everything is running fine without any error. In error function also response value remains undefined.
var toDoApp = angular.module('toDoApp');
toDoApp.factory('registrationService', function() {
var register = {};
register.registeruser = function(user, $http) {
$http({
method : "POST",
url : 'register',
data : user
}).then(function mySuccess(response) {
console.log("success");
}, function myError(response) {
console.log("error");
});
}
return register;
});
Inject the http service to the factory. Not the registeruser function.
toDoApp.factory('registrationService', function($http) {
Do some needful correction.
var toDoApp = angular.module('toDoApp',[]);
toDoApp.factory('registrationService', function($http) {
var register = {};
register.registeruser = function(user) {
$http({
method : "POST",
url : 'register',
data : user
}).then(function mySuccess(response) {
console.log("success");
}, function myError(response) {
console.log("error");
});
}
return register;
});
Error is showing because you did not inject $http service to to your toDoAppfactory not in your registeruser function . You should inject $http service to your factory. like :
toDoApp.factory('registrationService', function($http)
And your function registeruser should be like
register.registeruser = function(user) {
$http({
method : "POST",
url : 'register',
data : user
}).then(function mySuccess(response) {
console.log("success");
}, function myError(response) {
console.log("error");
});
}

How to design services to fetch data that are required to be called multiple times?

I have a service that returns a promise.
function GetSuggestedPeersService($http, SITE_CONFIG) {
var getSuggestedPeersService = this;
var data;
getSuggestedPeersService.getSuggestedPeersList = function() {
var baseUrl = SITE_CONFIG.baseUrl + "fetchSuggestedPeers";
var response = $http({
method : 'POST',
url : baseUrl,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
data : data
});
return response;
}
getSuggestedPeersService.setSuggestedPeers = function(suggestedPeers) {
getSuggestedPeersService.suggestedPeers = suggestedPeers;
}
getSuggestedPeersService.getSuggestedPeers = function() {
return getSuggestedPeersService.suggestedPeers;
}
}
Now I use the following in the Controller to resolve the promise:
//gets the suggested peers
var promiseSuggestedPeers = GetSuggestedPeersService.getSuggestedPeersList();
promiseSuggestedPeers.then(function (response) {
peerHealthController.GetSuggPeersShow = response.data;
GetSuggestedPeersService.setSuggestedPeers(peerHealthController.GetSuggPeersShow);
return peerHealthController.GetSuggPeersShow;
})
.catch(function (error) {
console.log("Something went terribly wrong Suggested Peers.");
});
Now my question is call this service multiple times and need to update this on other service calls as well.
What is the best way to write the controller part so as not to repeat the resolve promise every time I call the service?
It's been long time.
But I just wanted to answer this question.
The best way to design this would be to use a factory. So this will become a reusable service.
An example code can be the following:
var httpMethods = peerHealthApp.factory('HttpService',HttpService);
httpMethods.$inject = ['$http', 'SITE_CONFIG'];
function HttpService($http, SITE_CONFIG){
console.log("SITE_CONFIG from Peer Service: " + SITE_CONFIG);
var factory = {
httpGet : function(relativePath,data){
var baseUrl = SITE_CONFIG.baseUrl + relativePath;
var response = $http({
method : 'GET',
url : baseUrl,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
data : data
});
return response;
},
httpPost : function(relativePath, data){
var baseUrl = SITE_CONFIG.baseUrl + relativePath;
var response = $http({
method : 'POST',
url : baseUrl,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
},
data : data
});
return response;
}
};
return factory;
}
And the above can be used again and again like the following:
var data=$.param({
"url":moderatedArticleLink
});
var promiseURLMetaData = HttpService.httpPost("parseUrlMetadata", data);
promiseURLMetaData.then(function (response) {
var urlMetaData = response.data;
return urlMetaData;
})
.catch(function (error) {
console.log("Something went terribly wrong while trying to get URL Meta Data.");
});
What is the best way to write the controller part so as not to repeat the resolve promise every time I call the service?
Instead of saving the data in a service, I recommend saving the promise:
if ( !Service.get() ) {
var promise = Service.fetch();
Service.set(promise);
});
Service.get().then(function (response) {
$scope.data = response.data;
}).catch( function(errorResponse) {
console.log(errorResponse.status);
throw errorResponse;
});
By checking for the promise and only fetching if necessary, multiple controllers can share the data without caring about the order of controller instantiation. This avoids race conditions and multiple XHRs to the same resource.

Angular $http cache not working

I am trying to use angular's http cache but the result is undefined. Cache returns an object but usersCache is undefined.
controller in main.js
app.controller('exploreController', function($scope, dataService, $cookies, $cacheFactory, $http) {
// dataService.explorePosts();
$scope.explore = function(){
dataService.explorePosts();
var cache = $cacheFactory.get('$http');
console.log(cache);
var usersCache = cache.get('http://dstm.herokuapp.com/api/explore');
console.log(usersCache);
};
$scope.explore();
});
service in data.js
angular.module('dsnApp')
.service('dataService', function($http, $cookies, $cacheFactory) {
this.explorePosts = function(){
var id = $cookies.get("userId");
$http.get('http://dstm.herokuapp.com/api/explore', {cache: true,
params: {userId: id, page: 1},
})
.then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
console.log(response);
});
};
#charlietfl is right.
$http is asynchronous.Nothing will be cached until the request
completes and you are trying to access the cache synchronously.
To make this work as you expect:
First, make the this.explorePosts function return the promise, which $http service alredy returns.
this.explorePosts = function(){
var id = $cookies.get("userId");
return $http.get('http://dstm.herokuapp.com/api/explore', {cache: true,
params: {userId: id, page: 1},
})
.then(function successCallback(response) {
console.log(response);
}, function errorCallback(response) {
console.log(response);
});
};
Then use the cache in the promise's then callback.
$scope.explore = function() {
dataService.explorePosts().then(function () {
var cache = $cacheFactory.get('$http');
console.log(cache);
var usersCache = cache.get('http://dstm.herokuapp.com/api/explore');
console.log(usersCache);
});
};

Factory function not returning data

I have an angularjs factory to get data via $http.get():
'use strict';
app.factory('apiService', ['$http', function ($http) {
var apiService = {};
apiService.urlBase = 'http://localhost:1337/api/';
apiService.get = function (urlExtension) {
$http({
method: 'GET',
url: apiService.urlBase + urlExtension
}).then(function successCallback(response) {
return response.data;
}, function errorCallback(response) {
console.log(response);
});
}
return apiService;
}]);
The problem is, that it always returns undefined when i call the method apiService.get(); in a Controller. When I log the response data in the factory, it display the right data. The apiService.urlBase variable is always filled in my controller.
Do you guys have any suggestions or am I doing something wrong? Maybe it's a syntax error.
You are not returning the promise that is returned by $http. Add return before $http
Okay I solved the problem. I just passed a callback function via parameter for my get() function.
'use strict';
app.factory('apiService', ['$http', function ($http) {
var apiService = {};
apiService.urlBase = 'http://localhost:1337/api/';
apiService.get = function (urlExtension, callback) {
var data = {};
$http({
method: 'GET',
url: apiService.urlBase + urlExtension
}).then(function successCallback(response) {
data = response.data;
callback(data);
}, function errorCallback(response) {
console.log(response);
});
return data;
}
return apiService;
}]);

Cancelling ongoing Angular $http requests when there's a new request

How does one cancel an ongoing Angular $http request when there's a new request?
I've got an Angular app with a view that updates live as the user types. Sometimes old requests complete after the latest request, meaning the view displays the wrong data. What's the most straightforward way to cancel the previous request when there's a new one?
Using Angular 1.5, for what it's worth.
<input ng-model = "query" ng-keyup = "search()"/>
{{results | json}}
// In the controller:
$scope.search = function(){
$http({
method: "GET",
url: "/endpoint.php"
params: {
query: $scope.query
}
}).then(function(response){
$scope.results = response.data;
})
}
One solution I have tried:
// In the controller:
var canceler = $q.resolve(); // New
$scope.search = function(){
canceler.resolve("Canceling old request"); // New
$http({
method: "GET",
url: "/endpoint.php"
params: {
query: $scope.query
},
timeout: canceler.promise // New
}).then(function(response){
$scope.results = response.data;
})
}
In this scenario, even though I'm calling canceler.resolve before the $http request, the request turns up as "failed".
Any insights?
edit: Solution found!
// In the controller:
var canceler = $q.defer();
$scope.search = function(){
canceler.resolve("cancelled"); // Resolve the previous canceler
canceler = $q.defer(); // Important: Create a new canceler!
// Otherwise all $http requests made will fail
$http({
method: "GET",
url: "/endpoint.php"
params: {
query: $scope.query
}
}).then(function(response){
$scope.results = response.data;
})
}
When you start a new search, call the cancel() function. And you can use a resolved variable to make sure that you do not abort your $http call before it starts. Something like this:
var canceler = $q.defer();
var resolved = false;
var cancel = function() {
canceler.resolve("http call aborted");
};
$scope.search = function() {
if (resolved) {
cancel();
}
canceler = $q.defer();
resolved = true;
$http({
method: "GET",
url: "/endpoint.php"
params: {
query: $scope.query
}
timeout: canceler.promise
}).then(function(response) {
$scope.results = response.data;
resolved = false;
})
}
Don't forget to inject $q in your controller/directive/service.
The solution is to set up the promise, then with each search() cancel it and reinitialize a new one. This will reliably cancel any previous $http():
var canceler = $q.defer();
$scope.search = function() {
canceler.resolve();
canceler = $q.defer();
$http({
method: "GET",
url: "/endpoint.php"
params: {
query: $scope.query
}
timeout: canceler.promise
}).then(function(response) {
$scope.results = response.data;
})
}

Categories