I want to create a cache for my http requests, so I want to duplicate the $http callbacks.
this is my function:
function getData() {
if(cacheExists()) {
return cache;
}
return $http({
method: 'POST',
url: 'http://something.com',
params: {something}
});
}
and this is how I handle it:
getData()
.success(function(data) {
$scope.spot = data.data;
console.log($scope.spot);
}).error(function(data) {
console.log('error');
});
this will work perfectly with angularjs $http method,
but will not work with my "cache", becuase the "cache" should have those callbacks: success & error, how do I create them?
Its because the $http returns a promise. You can solve this by using the $q service and return the cache as a promise.
//inject $q
function getData() {
var deffered = $q.defer()
if(cacheExists()) {
deffered.resolve(cache);
} else {
$http({
method: 'POST',
url: 'http://something.com',
params: {something}
})
.success(function(data) {
deffered.resolve(data);
})
.error(function(response) {
deffered.reject(response);
})
}
return deffered.promise;
}
So what's happening here that you are creating "deffered" as a promise. A Promise is basically a way to handle async tasks. And when you get a promise you need to resolve it, as you did with your return value from the http call. But with a $q deffered you are using 'then' instead of 'success'. Consider the code snippet below:
getData()
.then(function(data) {
$scope.spot = data.data;
console.log($scope.spot);
})
Hope this helps.
UPDATE
As of you example by handling errors you could do this:
getData()
.then(function(data) {
if(data.data) {
$scope.spot = data.data;
console.log($scope.spot);
} else {
console.log("its an err");
}
});
Or this
getData()
.then(successCallback, errorCallback);
function successCallback(data) {
$scope.spot = data.data;
console.log($scope.spot);
}
function errorCallback() {
console.log("its an err");
}
Related
I've been learning/working on a newbie project which is basicly a simple task manager(similiar to those todo list projects). And I designed a user login page for this project and here is how it works.
So I have two functions siteLogin() for logging in and inside it I want to use second function showTasks() after user logs in which returns the usertasks it gets from API (promises I know).
So first I needed to return a value from a $http inside the showTasks() function but I ended up returning something like $$state so I searched and found couple of solutions on this website and so far I learned that $http doesn't return value but returns promises. So after couple of try&fail my code now runs until showTasks() and stops there.
So here is my code now.
Factory
app.factory('userTaskList', function ($http) {
return {
showTasks: function (userName) {
var tasks = { K_ADI: userName }; //UserName of the per
var $promise = $http({
method: 'POST',
url: 'http://localhost:5169/api/Isler/' + userName + '/IstenilenKayitCek',
headers: {
'Content-Type': 'application/json'
},
data: tasks
});
$promise.then(function successCallback(response) {
var data = response.data;
console.log("Factory data:", response);
return success(data);
}, function errorCallback(response) {
error("Error");
});
}
}
});
And my Controller:
app.controller('myCtrl', ['$scope', '$http', function ($scope, $http,userTaskList ) {
$scope.siteLogin = function () {
var loginMember = {
K_ADI: $scope.panel.loginUserName,
PAROLA: $scope.panel.loginPassword // HTML input
};
console.log(loginMember);
$http({
method: 'POST',
url: 'http://localhost:5169/api/Kullanicilar/KullaniciDogrula',
headers: {
'Content-Type': 'application/json'
},
data: loginMember
}).then(function successCallback(response) {
console.log("Message sent", response);
$scope.data = response.data.error.data;
if ($scope.data === true) {
console.log("User exists in database");
//RUNS UNTIL HERE AND STOPS
userTaskList.showTasks($scope.panel.loginUserName)
.then(function (res) {
$scope.gorev = res;
console.log("Fonk ici : ", $scope.gorev);
console.log("222222", res);
}, function (err) {
console.log(err);
});
console.log("outside func : ", $scope.gorev);
}
}, function errorCallback(response) {
console.log("Error: ", response);
});
}
}]);
This may be seen like a duplicate and there are many similiar problems on stack but I tried those solutions (I will link some later) still didn't solve my this problem plus some of them created other problems like this one. I tried to use $q , nested .then, and finally defining code in factory then calling its instance in module and so on. But still not working.
NOTE:Sorry for my poor English.
There are several errors in the showTasks function:
app.factory('userTaskList', function ($http) {
return {
showTasks: function (userName) {
var tasks = { K_ADI: userName }; //UserName of the per
var $promise = $http({
method: 'POST',
url: 'http://localhost:5169/api/Isler/' + userName + '/IstenilenKayitCek',
headers: {
'Content-Type': 'application/json'
},
data: tasks
});
var derivedPromise = $promise.then(function successCallback(response) {
var data = response.data;
console.log("Factory data:", response);
̶r̶e̶t̶u̶r̶n̶ ̶s̶u̶c̶c̶e̶s̶s̶(̶d̶a̶t̶a̶)̶;̶
//IMPORTANT
return data;
}, function errorCallback(response) {
̶e̶r̶r̶o̶r̶(̶"̶E̶r̶r̶o̶r̶"̶)̶;̶
console.log(response.status);
//IMPORTANT
throw response;
});
//IMPORTANT
return derivedPromise;
}
}
});
The desired data needs to be returned to the .then method success handler.
Errors in the error handler need to be re-thrown. Otherwise the rejected promise will be converted to a success with a value of undefined.
Finally the derived promise needs to be returned to the showTasks function.
Update
Do you think I call the function correctly inside the $scope.siteLogin ?
The dependency injection is wrong:
̶a̶p̶p̶.̶c̶o̶n̶t̶r̶o̶l̶l̶e̶r̶(̶'̶m̶y̶C̶t̶r̶l̶'̶,̶ ̶[̶'̶$̶s̶c̶o̶p̶e̶'̶,̶ ̶'̶$̶h̶t̶t̶p̶'̶,̶ ̶
function ($scope, $http,userTaskList ) {
Should BE
app.controller('myCtrl', ['$scope', '$http', 'userTaskList',
function ($scope, $http,userTaskList ) {
OR
app.controller('myCtrl', function ($scope, $http,userTaskList ) {
I have a request function :
function search(request) {
return $http.post('/path/to/resource', request);
}
I can call it like this :
search({/*...*/})
.success(function() {})
.error(function() {})
As I often need to find some objects by their ID, I need a shortcut function. I cannot find how to create this function so that I can also chain it with success() and error() functions.
I searched how to create a promise in angular and found the documentation about $q and this is what I tried :
function searchById(id) {
var deferred = $q.defer();
search({id: id}).
then(function (response) {
deferred.resolve(response.data.results[0]);
}, function (error) {
deferred.reject(error);
});
return deferred.promise;
}
I can only call it like this :
searchById().then(successCallback, errorCallback);
I would like to be able to call it like this :
searchById()
.success(successCallback)
.error(errorCallback);
The documentation about $q indicates that it returns a promise whereas the documentation about $http indicates that it returns an httpPromise but I cannot figure how to create an httpPromise.
Any idea?
In angular promises the error callback should be catch not error, try this
searchById()
.then(successCallback)
.catch(errorCallback);
sjokkogutten is correct that you don't need to use $q in this case you can simplify this
var deferred = $q.defer();
search({id: id}).
then(function (response) {
deferred.resolve(response.data.results[0]);
}, function (error) {
deferred.reject(error);
});
return deferred.promise;
to this
return search({id: id}).
then(function (response) {
return response.data.results[0];
}
$http is already returning a promise, so there is no need to use $q.defer(). Also, success() and error() has been depreciated (since 1.4.4), you should use then() instead.
Call your function like this:
search(request).then(function(data){
// successcallback
}, function(error){
// errorcallback
})
Creating a factory with $http functions will allow you to use .success and .error. But you really should be using .then.
app.factory("dataService", function($http) {
return {
search: function() {
return $http.get('path/to/api');
},
searchById: function(payload) {
return $http.post('path/to/api', payload);
},
searchMoreThings: function(payload) {
if(payload === "foo") payload = "bar";
return $http.post('path/to/api', payload);
}
}
});
You can do:
dataService.searchById(searchTerm).success().error();
Here is an actual example :
app.controller('controller',function($scope,$rootScope,$http,){
$scope.login = function(request){
var promise = $http.post(/path/to/resource, request, {
headers: {
'Content-Type': 'application/json'
}
}).then(function success(res){
//it worked, you have data in res
},function error(res){
// it failed
});
};
});
I'm trying to separate the $http.post() call into a ".factory()", But would like to fetch the response which is coming async on the controller. Is there a way of doing that?
Controller:
Login.post($scope.user);
Factory:
.factory( 'Login' , function($http,SERVERURL){
var serverUrl = SERVERURL;
return {
'post' : function(user){
$http.post(serverUrl+'/login', user).
then(function(response) {
console.log(response);
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
};
})
There is a .then() but I want that on the controller, so I can behave accordingly. Thank you!
Basically you need to return the $http.post promise, and from success function you could return a data that will return to the consumer of this method. So that you could easily call the factory method from controller & inside .then function of that call you could have success and error function.
Code
.factory('Login', function($http, SERVERURL) {
var serverUrl = SERVERURL;
return {
'post': function(user) {
return $http.post(serverUrl + '/login', user).
then(function(response) {
console.log(response);
return response.data; //return data from here
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
};
})
Controller
Login.post().then(function(data){ //success function
console.log(data)
}, function(error){ //error function
console.log(error);
})
You could add a callback param.
.factory( 'Login' , function($http,SERVERURL){
var serverUrl = SERVERURL;
return {
'post' : function(user, callback){
$http.post(serverUrl+'/login', user).
then(function(response) {
console.log(response);
callback(null, response);
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
callback(response);
});
}
};
})
And your controller will become:
Login.post($scope.user, function(err, response) {
if(err) {} //do something if there is an error
// or deal with the response
});
To return any response to controller just do:
return {
'post' : function(user){
return $http.post(serverUrl+'/login', user);
}
};
In your controller you will already call.then()
Angular's $http methods return a Promise.
The $http API is based on the deferred/promise APIs exposed by the $q service.
Factory
Your method post is not yet returning anything but can quite simply return the Promise which is created by calling $http.post:
.factory('Login' , function($http, SERVERURL){
var serverUrl = SERVERURL;
return {
'post' : function (user) {
return $http.post(serverUrl + '/login', user)
// ^^^^^^
.then(function (response) {
console.log(response);
return response.data;
}, function (response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
};
});
Controller
Then consume the result of the returned Promise by calling then on it:
Login.post($scope.user).then(function (res) {
// do something with `res`...
});
I wrote a angular js service which returns the response. But when I tried to call the service from the controller I am not able to get the exact response.
app.service('testservice', function($http){
var details= {};
details.getResponse = function() {
return $http({
url: 'send/getdata',
method: 'GET'
}).success(function(data, status, headers, config) {
this.getdata = data;
return getdata;
});
};
return details;
});
I am using the below controller to call the method.
app.controller('testcontroller',[ '$scope', '$http','testService',function($scope, $http,testService) {
var targetresponse = testService.getResponse();
alert(JSON.stringify(targetresponse))
})]);
I am getting the below response,
{"$$state":{"status":0,"pending":[[{"promise":{"$$state":{"status":0}}},null,null,null]]}}
Kindly, let me know the error here.
Your testservice service getResponse method should return a promise, and you can continue that promise chain inside your controller.
Service
details.getResponse = function() {
return $http({
url: 'send/getdata',
method: 'GET'
}).then(function(res) {
this.getdata = res.data;
return res.data;
});
};
You can use resolve that promise and get access of data inside .then function
var targetresponse = testService.getResponse();
targetresponse.then(function(data){
alert(JSON.stringify(data))
})
Srv.getData().then(function (success) {
var data = success.data;
$scope.myData = data;
}, function (error) {
});
Best way to to this.
Hello I'm new to AngularJs and trying to get json Data from my server. When the service gets executed, I see a clear response in Fiddler. But the success or the error function does not get executed, and so the service returns an empty array.
var app = angular.module('imageApp', []);
app.service('imageService', function ($http) {
var imageModels = [];
this.Images = function (url) {
$http({ method: 'GET', url: url }).success(function (data) {
imageModels = data;
}).error(function (data) {
imageModels = data || "Request failed";
});
return imageModels;
};
};
});
app.controller('ImageController', function (imageService, $scope) {
$scope.fetch = function (url) {
$scope.url = url;
$scope.ImageModels = imageService.Images($scope.url);
};
});
$http returns results asynchronously. So, return imageModels will execute before the success() or error() callbacks have had a chance to run. You need to wait for the promise that $http creates to resolve -- use then() in your controller.
Rather than repeat it here, see the solution from #Pete BD: https://stackoverflow.com/a/12513509/215945
Update your service like this.
app.service('imageService', function ($http, $q) {
this.Images = function (url) {
return $http({ method: 'GET', url: url }).success(function (data) {
$q.resolve(data);
}).error(function (data) {
$q.reject(data || "Request failed");
});
};
});
Then your controller, you can now wait for a promise to be returned from the service.
imageService.Images($scope.url)
.then(function(response){
// success
}).catch(function(error){
// error
})
So what happened? On your service, notice that we added $q to create a promise so we can reslove and reject the response from $http and make it "thenable" on the controller.
Writing a service to handle $http request is always a hassle for me, so I created this angular module to handle things for me. If you want you can check it out.