Calling additional service functions after a resolved promise in Angular - javascript

In Angular I have a service to access the google contacts api, then store all my contacts into variable (StorageVar) to be analyzed by other functions in the service.
Should I call one of the analysis functions before getting the data from the API, I want to call the getAPI function then (as in .then()) run the analysis function. The issue is that I can't figure out how to access any of the functions from the .then() scope.
angular.module('API',[])
.factory('API', ['$rootScope', '$http','$q', function ($rootScope, $http, $q) {
var StorageVar = [];
return{
getAPI: function(){
//does async call, returns promise, stores data into StorageVar
}
Analyze: function(){
if(StorageVar.length==0){
//need to get the data first
this.getAPI().then(function(){
//Analyze()
debugger;
}
}
}
In my controller I would want to use my service like this:
angular.module('views.local', ['API'])
.controller('localctrl',['API',function(API){
API.Analze()
//Callable even if the getAPI function hasn't run, so the Analyze function will take care of that.
}])
Any assistance is appreciated.

Is this what you mean?
angular.module('API',[])
.factory('API', ['$rootScope', '$http','$q', function ($rootScope, $http, $q) {
var StorageVar = [];
return{
getAPI: function(){
//does async call, returns promise, stores data into StorageVar
}
Analyze: function(){
if(StorageVar.length==0){
//need to get the data first
var _this = this;
this.getAPI().then(function(){
//Analyze()
_this.Analyze();
debugger;
}
}
}

Related

Service variable assigned data but it is always undefined when accessed

I am still new to angular so sorry if my question is a little ...
I created a service that invoke some REST API and I implemented it with promises.
I am currently with this promise return list of data to controller and put it in $scope.
I want that when I receive data in this function also store retrived data to service so I don't have to invoke service again if I already have data.
app.service("MyService", function ($http, $q) {
this.OrignalDataFromService = null;
return {
var deferred = $q.defer();
...
deferred.resolve(data);
this.OrignalDataFromService = data;
return deferred.promise;
}
}
Problem with this is that when I access OrignalDataFromService from controller it is always undefined (in promise I get data it's just service variable that is undefined) why is that?
I don't understand really where should model reside in angular app.
Is it $scope variable in controller and services are just here to allow us to get data from somewhere, or should model be inside service (as a variable)?
OrignalDataFromService is private variable for service, so if you want can access it you need return in object
check this
example:
app.service("MyService", function ($http, $q) {
this.OrignalDataFromService = null;
return {
originalData: this.OrignalDataFromService
}
}
Take a look at the fiddler here. You will have to expose the variable in which you are keeping the original data.
Service
myApp.service('myService', function($q) {
return {
OrignalDataFromService: null,
getData: function() {
var deferred = $q.defer();
var data = ["Data-1", "Data-2", "Data-3"]
deferred.resolve(data);
this.OrignalDataFromService = data;
return deferred.promise;
}
}
});

How to resolve a promise within another promise and get the resolution within a controller?

I have a function in a service returns a promise. I call this function from a different service where I want to alter the result of the promise and make this new altered value available to my controllers.
angular.module('test').service("service1", function($q) {
function doSomething(something) {
//parses some data
return deferred.promise;
}
return {
doSomething: doSomething
}
});
angular.module('test').service("service2", ['service1', $q, function(service1, $q) {
var deferred = $q.defer();
var myResult = deferred.promise;
service1.doSomething("test").then(function (result) {
var alteredResult = result + "Altered"; //result I want to be accessible by my controllers
deferred.resolve(alteredResult)
});
return {
myResult: myResult
}
}]);
angular.module('test').controller('testController', ['$scope', 'service2', function ($scope, service2) {
$scope.test = service2.myResult;
}]);
It obviously didn’t work when I was initializing myResult outside of the .then() and updating it inside because myResult was passed to the controller before it was altered. This lead me to try creating another promise inside of service2.
After all of this, I get a promise in $scope.test but it ends up being a blank {} javascript object.
How can I properly store the altered result of service2 so that I can access it from my controllers?
Thanks you very much for your time. Let me know if you need additional information or if I am being unclear.
You are assigning promise to the scope variable. You should resolve the promise (promise chain) and assign the resolved value instead.
service2.myResult.then(function(result) {
$scope.test = result;
});

When calling a function that returns a function that returns a function, how do you get data at the bottom?

How can I access the data from the function inside the function inside the function I'm returning?
projectsRsrc.factory('projectsSrvc', ['$resource', function($resource){
return function(name){
var url = "http://localhost/proj/v3/apiSimulations/projects.json";
var resource = $resource(url);
return resource.get(function(data){
return data;
});
}
}]);
I want to get this data in my controller.
projectsApp.controller('projectsCtrl', ['$scope', 'projectsSrvc', function($scope, projectsSrvc){
$scope.projects = projectsSrvc(name);
}
But projectsSrvc returns a function, and I'm not really sure how to access the function it is returning. Ultimately I want the data to be assigned in my controller
Your factory returns a function and that function returns a promise so in your controller your code should be like this:
projectsSrvc(name).then(function(data) {
$scope.projects = data;
});
Edit: I mixed up $resource with $http so things seem a little different, however everything is explained here: https://docs.angularjs.org/api/ngResource/service/$resource
I got it to work by changing the code to this:
projectsSrvc(name).$promise.then(function(data) {
$scope.projects = data;
});
Tested here: http://jsbin.com/vepivacosa/1/edit?html,js,console
You just need another set of parantheses
$scope.projects = projectsSrvc(name)(argumentmustbepassedhereforthefunction);
But note that you'll need some callback kind of thing(or promises may be?) as you're returning from the ajax call which is asynchronous.
BTW the above code is just a one-liner for
var func = projectsSrvc(name); // store the function reference
$.scope.projects = func(argumentmustbepassedhereforthefunction);

Angular + requirejs - the controller cannot pick up ajax return data from the factory?

My controller cannot pick up the data that processed from $http.get() in requirejs environment. Any idea how can I fix it?
UserFactory.js
define(['app'], function (app) {
app.module1.factory('UserFactory', ['$http', function($http) {
//your minsafe controller
var factory = {};
factory.getUsers = function(){
$http.get('api.php').success(function(data) {
// here the data from the api is assigned to a variable named users
return data; // [{"id":"1","name":"Big Kev","email":"bigkev#example.com"},{"id":"2","name":"Judy","email":"punk#example.net"},{"id":"3","name":"Suzy","email":"suzy#example.com"},{"id":"4","name":"Joey","email":"sheena#example.org"},{"id":"5","name":"DeeD","email":"deedee#example.net"}]
});
};
return factory;
}]);
});
view.js,
define(['app'], function (app) {
app.module1.controller('View1Ctrl', ['$scope','UserFactory', function($scope,userFactory) {
//your minsafe controller
$scope.message = "Message from View1Ctrl";
$scope.users = userFactory.getUsers();
console.log($scope.users); // undefined
}]);
});
as you can see, I get undefined for $scope.users. It seems that console.log($scope.users); is executed before $http.get('api.php') in the factory. How can I fix this then?
This has nothing to do with Require; it is a very common misconception about how asynchronous code runs (especially promises).
You see factory.getUsers() makes an asynchronous call. The response will be available at a later time and success will be called with the response data at that later time. On the other hand, $scope.users = userFactory.getUsers() is synchronous. It is almost guaranteed that the async call wll NOT have returned by the time the next statement runs. And even if it has returned, the callback will NOT have run because Javascript is single threaded in the browser.
Moreover you have another serious fault: the success callback is "procedural" in the sense that it receives the response and has to do something with it. Its return value is disregarded!
To use promises (or at least $http) correctly in this case, change factory.getUsers to return the $http promise:
factory.getUsers = function(){
return $http.get('api.php');
};
And change the controller to use the promise or the success/error callbacks:
// option (1) with promise
userFactory.getUsers().then(function(response) {
$scope.users = response.data;
});
// option (2) callback
userFactory.getUsers().success(function(data) {
$scope.users = data;
});

how do I access child elements of JSON in the controller in Angular JS

I don't understand how to wait for the resource call to finish before assigning the data.properties to $scope in my controller.
here is my confusion:
i have a resource call that returns this:
[
{
"PreAlertInventory": "5.000000",
"SharesInInventory": "3.000000",
"TotalSharesSold": "2.000000",
"TotalMoneySharesSold": "18.000000",
"TotalSharesBought": "0.000000",
"TotalShareCost": "0.000000",
"EstimatedLosses": "0.000000"
}
]
here is the applicable code from the controller:
$scope.alertSwap = function () {
var data = Data.query(); // gets the data. works as expected
//$scope.test = data; //works as expected. can access data and properties in template
$scope.test = data.TotalMoneySharesSold; //does not work. is empty???
}
i can access the array and its properties from the template BUT not from inside the controller.
How do I access the child elements from inside the controller that called the resource?
http://plnkr.co/edit/JnLqq4v7lKlYOHg85Jma?p=preview
answer: thanks to all who helped:
I needed to assign a callback to the resource call, and assign the elements from within the function:
$scope.data = Data.query(myParams, function(data) {
$scope.test = data[0].TotalSharesBought;
});
Your data would appear to be returned as an array, try $scope.testTwo = data[0].TotalSharesBought.
I've updated your Plunkr accordingly.
As said above it is likely you are fetching those data async. I updated your code to support promise (which makes your code async and may not fit with the rest of the application by the way).
$timeout simulates an async call. In your factory service:
var deferred = $q.defer();
$timeout(function() {
return deferred.resolve(data);
}, 100); // set it to zero to return immediately
return deferred.promise;
In your controller call you factory factory method query() and hook the response with then, which is the promise part of the snippet:
Data.query().then(function(response) {
$scope.test = response[0].TotalMoneySharesSold;
});
http://plnkr.co/edit/SGGCVS?p=preview

Categories

Resources