sum of random numbers using angularjs promises - javascript

app.service("service1", function ($q) {
this.number1 = function (num1) {
var deferred = $q.defer();
var num1 = Math.floor((Math.random() * 5) + 1);
var result1 = num1;
deferred.resolve(result1);
return deferred.promise;
}
});
app.service("service2", function ($q) {
this.number2 = function (num2) {
var deferred = $q.defer();
var num2 = Math.floor((Math.random() * 5) + 1);
var result2 = num2;
deferred.resolve(result2);
return deferred.promise;
}
});
app.service("addservice", function ($q) {
this.addition = function (num1, num2) {
var deferred = $q.defer();
var result = num1 + num2;
deferred.resolve(result);
return deferred.promise;
}
});
app.controller('myCtrl', function ($scope, addservice, service1, service2) {
service1.number1().then(function (data) {
$scope.result1 = data;
})
service2.number2().then(function (data) {
$scope.result2 = data;
})
addservice.addition($scope.result1, $scope.result2).then(function (data) {
$scope.result = data;
});
});
service1 is used to pass num1 and service2 for num2. Service3 is used for the sum of those numbers.
How to use $q.all() here to sync multiple promises.?

You can use $q.all() method, it takes either an object or an array of promises and waits for all of them to resolve() or one of them to reject() and then executes the provided callback function.
//In $q as dependecies
app.controller('myCtrl', function ($scope, addservice, service1, service2, $q) {
//Persist reference of promomise
var p1 = service1.number1().then(function (data) {
$scope.result1 = data;
});
//Persist reference of promomise
var p2 = service2.number2().then(function (data) {
$scope.result2 = data;
});
//Pass references
$q.all([p1, p2]).then(function () {
//Now pass result 1 and 2
addservice.addition($scope.result1, $scope.result2).then(function (data) {
$scope.result = data;
})
});
});

You can return both values and use them in a synced promise:
app.controller('myCtrl', function($scope, addservice, service1, service2) {
var promise1 = service1.number1().then(function(data) {
$scope.result1 = data;
return data;
})
var promise2 = service2.number2().then(function(data) {
$scope.result2 = data;
return data;
})
$q.all([promise1, promise2]).then(function(res) {
addservice.addition(res[0], res[1]).then(function(data) {
$scope.result = data;
});
})
});

Related

angular.foreach inside a promise

I'm trying to create a function that returns a promise and inside that function I have an angular.forEach that returns a promise.
Here is an example code:
function func1() {
func2(demoText, demoObject).then(function(response) {
console.log(response);
});
}
function func2(demoText, demoObject) {
var deferred = $q.defer();
var returnString = "someReturnString";
var keepGoing = true;
var loopPromises = [];
angular.forEach(demoObject, function(value, key) {
if(keepGoing) {
var deferred2 = $q.defer();
loopPromises.push(deferred2.promise);
if(value.type == 'other') {
someService.getDataFromServer()
.then(function(serverResponse) {
returnString = serverResponse;
deferred2.resolve();
});
keepGoing = false;
}
else {
deferred2.resolve();
}
}
});
return $q.all(loopPromises).then(function () {
deferred.resolve(returnString);
return deferred.promise;
});
}
Now the returned value is "someReturnString" which means that the value is retuned before I'm getting the result from the server.
How can this be resolved?

Call factory function once

I have this factory which is called multiple times by directives. Since it returns a lot of data the rendering at the end is slow. How can i call it only once or save it in a cashe when its called the second time and n time?
appBMdata.factory('Trends',['$http','Config','$q',
function($http,Config,$q){
function getAllData() {
var source1 = $http.get(Config.api_server + 'bizmonitor/indicators/get/2016');
var source2 = $http.post(Config.api_server + 'trends');
return $q.all([source1, source2]);
};
return {
getAllData : getAllData,
};
}]);
You can save the promise in a var, and return it if it has been already set:
appBMdata.factory('Trends',['$http','Config','$q',
function($http,Config,$q){
var _cacheGetAllData;
function getAllData() {
var source1 = $http.get(Config.api_server + 'bizmonitor/indicators/get/2016');
var source2 = $http.post(Config.api_server + 'trends');
_cacheGetAllData = _cacheGetAllData || $q.all([source1, source2]);
return _cacheGetAllData;
}
return {
getAllData : getAllData,
};
}]);
If you want successive calls to force to update, you can edit it to something like this:
appBMdata.factory('Trends',['$http','Config','$q',
function($http,Config,$q){
var _cacheGetAllData;
function getAllData(ignoreCache) {
var source1 = $http.get(Config.api_server + 'bizmonitor/indicators/get/2016');
var source2 = $http.post(Config.api_server + 'trends');
if (ignoreCache) {_cacheGetAllData = undefined;}
_cacheGetAllData = _cacheGetAllData || $q.all([source1, source2]);
return _cacheGetAllData;
}
return {
getAllData : getAllData,
};
}]);
I'm resolving it in the service and then store data, if it has data, returning data in a promise. If you want to fetch data again just add true as first arguement.
appBMdata.factory('Trends', ['$http', 'Config', '$q', function($http, Config, $q) {
var data;
function getAllData(nocache) {
var deferred = $q.defer();
if (data.length && !nocache) {
deferred.resolve(data);
} else {
var source1 = $http.get(Config.api_server + 'bizmonitor/indicators/get/2016');
var source2 = $http.post(Config.api_server + 'trends');
$q.all([source1, source2])
.then(function (values) {
data = values;
deferred.resolve(data);
})
.catch(function (err) {
deferred.reject(err);
});
}
return deferred.promise;
}
return {
getAllData : getAllData
};
}]);
Yes you can keep the data on $rootScope and return the data from there when its called multiple times.
appBMdata.factory('Trends',['$http','Config','$q','$rootScope'
function($http,Config,$q,$rootScope){
function getAllData() {
var source1 = $http.get(Config.api_server + 'bizmonitor/indicators/get/2016');
var source2 = $http.post(Config.api_server + 'trends');
return $q.all([source1, source2]);
};
if($rootScope.data){ // check if data already present
$rootScope.data=getAllData(); // assign data to rootscope
}
return {
getAllData : $rootScope.data, //return data from rootscope
};
}]);

Passing data from promise then method to an object method

How to pass data from promise then method to an object method.
this.httpReq(url).then(function (data) {
this.storeData(data);
});
I know that here I'm out of scope and this doesn't refer to my object. But, nevertheless, I can't understand how to resolve it.
Bellow you can find entire code snippet. In the end, I want to get data from the service API and store it in the object array property this.storage.
var http = require('http');
function CoubApi (url) {
this.url = url;
this.storage = [];
this.httpReq = httpReq;
this.searchData = searchData;
this.storeData = storeData;
}
function httpReq (url) {
var promise = new Promise (function (resolve, reject) {
http.get(url, function (res) {
var data = '';
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
if(data.length > 0) {
resolve(JSON.parse(data));
} else {
reject("Error: HTTP request rejected!");
}
});
}).on('error', function (err) {
console.log("Error: ", e);
});
});
return promise;
}
function storeData (data) {
var i;
console.log("Storrrreee");
for(i = 0; i < 10; i++) {
this.storage.push(data.coubs[i]);
}
}
function searchData (searchtext, order, page) {
var url = this.url+
"search?q="+searchtext+
"&order_by="+order+
"&page="+page;
this.httpReq(url).then(function (data) {
this.storeData(data);
});
}
var coub = new CoubApi("http://coub.com/api/v2/");
coub.searchData("cat", "newest_popular", 1);
console.log(coub.storage);
You can store this in varaible:
var self = this;
this.httpReq(url).then(function (data) {
self.storeData(data);
});
or use bind:
this.httpReq(url).then(function (data) {
this.storeData(data);
}.bind(this));

angular trying to read a property in service

In the script below i try to access the data from the cartDataService, even though i manage to read this.test from the cartDataService, i get an empty value for the cart_id. I know it is due to the asynchronous characteristics of javascript
i am pretty sure that i try to access the cart_id from the service before it is assigned, how do i make sure that the cart_id from the service is assigned? thank you
var app = angular.module('myApp', [])
app.service('cartDataService', function () {
this.cart_id = ""
this.getcart_id = function(){ return this.cart_id};
this.setcart_id = function(id){
this.cart_id = id
}
this.test = "byebye"
})
app.controller('OrderDetailCtrl', ['$http', 'cartDataService', function ($http, cartDataService) {
var self = this
self.msg = 'Order Detail'
self.order_id = outer_id
self.orders = {
get: function () {
return $http.get('http://apimucommerce/api/order/' + self.order_id + '/')
.then(function (response) {
return response.data
})
}
}
self.orders.get().then(function (data) {
self.order = data
self.cart_id = self.order.cart_id
cartDataService.setcart_id(self.order.cart_id)
})
}])
app.controller('CartController', ['cartDataService', function (cartDataService) {
var self = this
self.cart_id = cartDataService.getcart_id()
alert(cartDataService.cart_id)
self.msg = cartDataService.test
}])
You can use this:
app.controller('CartController', ['$scope', 'cartDataService', function ($scope, cartDataService) {
var self = this
$scope.$watch(
function () watcher{
return cartDataService.getcart_id();
},
function () onCardIdChanged{
self.cart_id = cartDataService.getcart_id()
alert(self.cart_id);
}
);
}]);
Another way to solve your problem:
app.service('cartDataService', ['$q', function ($q) {
var deffered = $q.defer();
this.cart_id = "";
this.getcart_id = function(){
return deffered.promise;
};
this.setcart_id = function(id){
this.cart_id = id;
deffered.resolve(;
}
}]);
app.controller('CartController', ['$scope', 'cartDataService', function ($scope, cartDataService) {
var self = this;
cartDataService.getcart_id().then(function (cardId) {
self.cart_id = cartDataService.getcart_id()
alert(self.cart_id);
});
}]);
UPD:
app.service('cartDataService', ['$q', function ($q) {
var deffered = $q.defer();
this.cart_id = "";
this.getcart_id = function(){
return deffered.promise;
};
this.setcart_id = function(id){
this.cart_id = id;
deffered.resolve(id);
}
}]);
app.controller('CartController', ['$scope', 'cartDataService', function ($scope, cartDataService) {
var self = this;
cartDataService.getcart_id().then(function (cardId) {
self.cart_id = cardId;
alert(self.cart_id);
});
}]);

Error dealing with $q.all and promises in AngularJS

Given the following code:
function Ctrl($scope, $http, $q) {
var search = function(name) {
if (name) {
$http.get('http://api.discogs.com/database/search?type=artist&q='+ name +'&page=1&per_page=5').
success(function(data3) {
$scope.clicked = false;
$scope.results = data3.results;
});
}
$scope.reset = function () {
$scope.sliding = false;
$scope.name = undefined;
};
};
$scope.$watch('name', search, true);
var done = $scope.getDetails = function (id) {
$scope.clicked = true;
$scope.sliding = true;
var api = 'http://api.discogs.com/artists/';
return $q.all([$http.get(api + id),
$http.get(api + id + '/releases?page=1&per_page=100')]);
};
done.then(function (){
$scope.releases = data2.releases;
$scope.artist = data;
return $http.get('http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=e8aefa857fc74255570c1ee62b01cdba&artist=' + name + '&album='+ title +'&format=json');
});
I'm getting the following console error:
TypeError: Object function (id) {
$scope.clicked = true;
$scope.sliding = true;
var api = 'http://api.discogs.com/artists/';
return $q.all([$http.get(api + id),
$http.get(api + id + '/releases?page=...<omitted>... } has no method 'then'
at new Ctrl (file:///C:/Users/Zuh/Desktop/AngularJS%20Discogs/js/services.js:27:9)
Can anybody point me to where might the error be? I'm defining the .then after getDetails is executed...
Here's a working Plunker.
Here is your updated plunkr http://plnkr.co/edit/lTdnkRB1WfHqPusaJmg2?p=preview
angular.module('myApp', ['ngResource']);
function Ctrl($scope, $http, $q) {
var search = function(name) {
if (name) {
$http.get('http://api.discogs.com/database/search?type=artist&q='+ name +'&page=1&per_page=5').
success(function(data3) {
console.log(arguments)
$scope.clicked = false;
$scope.results = data3.results;
});
}
$scope.reset = function () {
$scope.sliding = false;
$scope.name = undefined;
};
};
$scope.$watch('name', search, true);
var done = $scope.getDetails = function (id) {
$scope.clicked = true;
$scope.sliding = true;
var api = 'http://api.discogs.com/artists/';
var q = $q.all([$http.get(api + id),
$http.get(api + id + '/releases?page=1&per_page=100')])
.then(function (ret){
//console.log(arguments)
$scope.releases = ret[1].data.releases;
$scope.artist = ret[0];
return $http.get('http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=e8aefa857fc74255570c1ee62b01cdba&artist=' + name + '&album='+ title +'&format=json');
})
return q
};
}
To sum up fixes:
move $q.all().then() part into done method
pay more attention to what parameters handlers received in then part.

Categories