angular, correct way for a function callback - javascript

I am writing an ItemProvider for my app in angular js.
I chose a service.
app.factory('ItemProvider', function($http) {
var url = "http://localhost:7888/api.php/json?";
return {
get_data: function() {
$http.get(url).
success(function(data,status,headers,config) {
json = data;
console.log("app returned ok");
console.log(json);
callback(json);
}).
error(function(data,status,headers,config) {
console.log("Error getting data from app!");
json = data;
callback(json);
});
callback = function(json) {
console.log("callback");
return json;
}
console.log("already done");
}
};
});
Of course what happens here is that get_data returns immediately before the actual calls to the backend via $http returned...
How do I correctly have a get_data function which will return the data from the backend? I tried adding a callback (see code above) but I realize by the time it's getting called, get_data already finished as well...

$http is hardcoded to only work asynchronously, meaning your only option is to code with that in mind. Due to this, it isn't possible for get_data to directly return the data, instead, it has to either accept a callback, or return a promise. The promise route is far easier in my opinion.
app.factory('ItemProvider', function($http) {
var url = "http://localhost:7888/api.php/json?";
return {
get_data: function(url) {
return $http.get(url);
}
};
});
example usage:
//...
ItemProvider.get_data('/items')
.success(function (items) {
console.log(items);
})
.error(function () {...});
//...

Related

Promise returning before $http promise concludes

I need to have one function call a second function where the second function includes some setup code, an http callback to a REST server and then finely some cleanup code before returning to the first function. The idea is to have the first function then displays a result message after the second function is finished.
The following example returns from the second function before it finishes the callback so I don't get the results of the http success or error.
var saveData = function(_this){
return new Promise(function(resolve,reject){
resolve( _this.Save('SavExit') );
});
};
saveData(this).then(function(httpResponse){
// display response after http callback finishes
console.log(httpResponse);
});
this.Save = function (lcAction) {
// validate data
$http.post('serverCallback.aspx',oSelectedVendor).
success(function (data, status, headers, config) {
// process data before returning;
return true;
}).
error(function(data,status,headers,config){
console.log(data);
return false;
});
};
You need to return Promise from the Save method:
this.Save = function (lcAction) {
// validate data
return $http.post('serverCallback.aspx',oSelectedVendor).
success(function (data, status, headers, config) {
// process data before returning;
return true;
}).
error(function(data,status,headers,config){
console.log(data);
return false;
});
};
Note return I added in front of $http.
In addition, since you return Promise from Save, you don't need another one in saveData:
var saveData = function(_this) {
return _this.Save('SavExit')
};

AngularJS factory returning State object instead of JSON data from promise

I have made two factory and calling first from second one, consuming second one factory in controller but instead of getting data as JSON, I'm getting data as $$State.
I'm new to angularJS tried many ways but not able to solve, please help.
app.factory('userDetails', ['APIService', '$q', function (APIService, $q) {
getDetails: function () {
var deferred = $q.defer();
var getFunc = function () {
APIService.doGetCall('Masters/employee/username/tarun')
.then(
function (data)
{
deferred.resolve(data);
},
function (data, status, headers, config)
{
deferred.reject('There was an error creating object'); })
return deferred.promise;
}
var a = getFunc();
return a;
}
}
vm.user = userDetails.getDetails();
console.log("user",vm.user);
response is as per below snippet
Response
You should be using .then function to get response there. Rather I'd say you don't need to create extra promise, its an anti-pattern. Where you could utilize the promise return by doGetCall method directly.
app.factory('userDetails', ['APIService', '$q', function(APIService, $q) {
getDetails: function() {
var getFunc = function() {
return APIService.doGetCall('Masters/employee/username/tarun');
}
var a = getFunc();
return a;
}
}]);
vm.user = userDetails.getDetails().then(function(response){
console.log(response.data);
vm.user = response.data;
console.log("user", vm.user);
}, function(error){
console.log(error)
}).catch(exceptionHandler);
userDetails.getDetails() returns a promise, Hence you need to use .then(onsuccess, onRejected)
userDetails.getDetails().then(function(data){
vm.user = data;
console.log("user",vm.user);
});
You've got the
return deferred.promise;
line inside the APIService.doGetCall function. It should be outside of it.

Combining 2 promises in angularjs

Im combining 2 promises but isnt working, in a service i have 2 methods, where the method "UserService.getAuthenticatedUser()" gets the current user information and than there is a "UserService.getAccountTypeData(idUser)", where gets the usertype information, but to get to the second method i need the userID, so basically first i call the "UserService.getAuthenticatedUser()", get the id, and than call "UserService.getAccountTypeData(idUser)", but isnt working.
function isAccount(accountName) {
UserService.getAuthenticatedUser()
.then(function (response) {
var userDetails = response.data;
});
UserService.getAccountTypeData(idUser)
.then(function (response) {
var userDetails = response.data;
return userDetails;
});
}
PS: I already injected the service...
You can chain your promises by returning values from your .then() functions.
function isAccount(accountName) {
return UserService.getAuthenticatedUser(accountName) // pass in accountName argument?
.then(function(response) {
var userDetails = response.data;
return userDetails.Id; // user id value
})
.then(UserService.getAccountTypeData) // userDetails.Id gets passed to getAccounttypeData method
.then(function(response) {
var userDetails = response.data;
return userDetails;
});
}
// usage
isAccount('AccountA').then(function(userDetails) {
// do something with userDetails
});
You're dealing with asynchronous calls, so when you call the .then() method, it's executing the function and wiring up the callback to an anonymous function passed as a parameter to then(). If the second is dependent on the first, you could nest them like this...
function isAccount(accountName) {
UserService.getAuthenticatedUser()
.then(function (response) {
var userDetails = response.data;
UserService.getAccountTypeData(idUser)
.then(function (response) {
var userDetails = response.data;
return userDetails;
});
});
}

AngularJS: Why is .then() not waiting for the promise object to arrive

I have created the following angular service for the purpose of making the API calls.
(function (module) {
module.service('APIService',function ($http, $q) {
console.log("Reached APIService")
var deferred = $q.defer();
this.getData = function (requestURL) {
console.log("Reached APIService #GET", requestURL);
$http.get(requestURL).success(
function (data, status) {
deferred.resolve(data);
console.log("In service",status,data);
}).error(
function (data, status) {
deferred.reject(data);
console.log(status);
});
return deferred.promise;
};
this.postData = function (requestURL, requestObj) {
console.log("Reached APIService #POST", requestURL, requestObj);
$http.post(requestURL, requestObj).success(
function (data, status) {
deferred.resolve(data);
console.log(status);
}).error(
function (data, status) {
deferred.reject(data);
console.log(status);
});
return deferred.promise;
};
});
}(angular.module("MainApp")));
I have injected it in my two controllers. However, I am facing following issues:
When I call it first time in first controller, it works fine and returns the desired result. However, when I call it in second controller as follows:
APIService.getData(Config + headerURL).then(function (response) {
console.log(Config + headerURL);
console.log("header response from API", response);
},function(error) {
console.log("API call for header data failed");
});
Since my service returns a promise object, I don't expect the code inside .then() to work before the service data arrives.
However, it runs before service data arrives (no clue how). The most strange thing is that the response that I get inside .then() is not actually the response from this URL (Config+headerURL), but it is the response that was obtained from a different URL previously called in first Controller using the same APIService service.
Just to inform: the actual response from current URL do arrive at a later stage.
I am aware of asynchronous callings and I think it has something to do in this case, but I guess .then() handles it in Angular. So I am confused what is the issue here. Can anyone shed some light please?
Since the service is a singleton, you only have a single instance of the deferred object.
Once resolved, it will keep being resolved, so the next time you call, getData, it will return immediately.
You could move:
var deferred = $q.defer();
inside both your getData and postData function.
Or you could just return the promise that $http creates.
Just try this, You need to return to the http result.
this.getData = function (requestURL) {
console.log("Reached APIService #GET", requestURL);
return $http.get(requestURL) };
Looks like you have to disable cache explicitly within $http call.
$http.get({
url: requestURL,
cache: false
})
You are using an anti-pattern by creating your own promises when $http already returns a promise.
Get rid of $q altogether in this service and simply return $http
this.getData = function (requestURL) {
console.log("Reached APIService #GET", requestURL);
return $http.get(requestURL).then(function (response) {
return response.data;
console.log("In service", status, data);
}, function () {
// errror handling here
});
};

Javascript function return undefined

I've an AngularJS project and there the is a get request is made to the backend like this which will return the data and this function is used because the get request to the same url is made multiple times
function getfunction(some input data) {
$http.get('requset URL' , { params : {some parameters})
.success(function(data){
return data;
});
}
var output = getfunction(input data to the function);
However the output is always undefined how can I fix it so the output will have the values returned from the above get request.
$http returns a promise. Your data will arrive asynchronously.
function getfunction(some input data) {
return $http.get('requset URL' , { params : {some parameters});
}
var output;
getfunction(input data to the function).then(function(data){
output = data;
}, function(){
// Handle errors.
});
$http.get uses promises. Or in other words: it does the request asynchronously.
You can return what $http.get returns itself - a promise - and add a continuation using then:
function getfunction(some input data) {
return $http.get('requset URL' , { params : {some parameters});
}
getfunction(input data to the function).then(function(data) {
});
// or .success
getfunction(input data to the function).success(function(data) {
});
The call is asynchronous, so the function you are calling will run first and then the success callback will run when the response is returned from your get request. The success handler should be what handles the output in this scenario (e.g showing the return value in a textbox)
$http return $promise. so either you use $q service :
function getfunction(some input data) {
var deferred = $q.defer();
$http.get('requset URL' , { params : {some parameters})
.success(function(data){
deferred.resolve(data)
});
return deferred.promise;
}
var output = getfunction(input data to the function).then(function(data){
output = data;
}, function(err){
console.log(err)
});
or
function getfunction(some input data) {
return $http.get('requset URL' , { params : {some parameters});
}
var output;
getfunction(input data to the function).then(function(data){
output = data;
}, function(err){
console.log(err)
});

Categories

Resources