I'm tring to call 2 functions, and each one cancel the other. I'm using ionic and angularjs $interval. This is my code:
var promise;
var promise2;
$scope.$on('mapInitialized', function(event, map) {
var justLocation = window.localStorage.getItem('justLocation');
var tracage = window.localStorage.getItem('tracage');
//Location defined function
//traceDirection defined function
if(justLocation==1){
$interval.cancel(promise2);
promise = $interval(Location, 5000);
} else if(tracage==1) {
$interval.cancel(promise);
promise2 = $interval(traceDirection, 5000);
}
});
But when I'm running the code, the 2 function running at the same time, please any idea about my problem
Related
While I am loading an AngularJS file my code is getting executed completely before the code in .then function completes its execution. How to pause code till the code in .then function executes. I mean I want to make synchronous ajax calls, I used to use async: false in jQuery. I want to know how to do that in angularJS.
Thanks in advance
Below is my AngularJS code
var app = angular.module('myApp', [ ]);
app.controller("Ctrl",Ctrl);
function Ctrl($http){
var self=this
ajaxCall();
function ajaxCall(){
return $http.get('/getData/')
.then(function(data){
// this below alert should come before the last alert
alert(" should execute first then below alert")
self.data=data
})
}
alert("getting executed first")
}
Your ajaxCall() is returning a promise. So you can simply wait until it finished.
The $http API is based on the deferred/promise APIs exposed by the $q service. While for simple usage patterns this doesn't matter much, for advanced usage it is important to familiarize yourself with these APIs and the guarantees they provide.
AngularJS $http documentation
var app = angular.module('myApp', [ ]);
app.controller("Ctrl",Ctrl);
function Ctrl($http){
var self = this;
function ajaxCall(){
return $http.get('/getData/')
.then(function(data) {
// this below alert should come before the last alert
alert(" should execute first then below alert")
self.data = data;
}
);
}
// You can use .then here, because ajaxCall returns a promise
ajaxCall().then(function () {
alert("getting executed first");
})
}
What if you chain promises?
function Ctrl($http, $q){
var self = this;
ajaxCall();
function ajaxCall(){
return $http.get('/getData/')
.then(storeData)
.then(proceed);
}
function storeData(response) {
alert("1st");
self.data = response.data;
return $q.when(self.data);
}
function proceed(data) {
alert("2nd");
}
}
In my AngularJS application, I have a controller-A and a factory. I am using the following code in factory to call the function in controller-A. In the initial call, the function in controller A's function executes 1 time; on the next call the controller-A's function executes 2 times. Hence the number of times executed get increased for each call. Is it possible to avoid this, please advise me. I have added the factory code and controller-A code below:
Factory code:
updateUserData: function (value, action) {
$("#myModalInsertUser").modal('hide');
var id = value.Id;
var params = {};
params.id = depotId;
$rootScope.selectedId = params;
$rootScope.$emit("EVENT_1", {id});
});
Controller-A code:
var listener = $rootScope.$on("EVENT_1", function(event, params, reload) {
$scope.confirmUserInfo(params);
});
$scope.confirmUserInfo = function(params) {
$('#myModalConfirmUser').modal('show');
$('#closeConfirmUser').unbind('click').click(function () {
$('#myModalConfirmUser').modal('hide');
var params = $rootScope.selectedId;
$scope.getUsers(params);
$scope.$on('$destroy', listener);
});
}
Attach the event listener to $scope and it will be automatically destroyed when the scope is destroyed:
̶v̶a̶r̶ ̶l̶i̶s̶t̶e̶n̶e̶r̶ ̶=̶ ̶$̶r̶o̶o̶t̶S̶c̶o̶p̶e̶.̶$̶o̶n̶(̶"̶E̶V̶E̶N̶T̶_̶1̶"̶,̶ ̶f̶u̶n̶c̶t̶i̶o̶n̶(̶e̶v̶e̶n̶t̶,̶ ̶p̶a̶r̶a̶m̶s̶,̶ ̶r̶e̶l̶o̶a̶d̶)̶ ̶{̶
var deregisterFn = $scope.$on("EVENT_1", function(event, params, reload) {
$scope.confirmUserInfo(params);
});
$scope.confirmUserInfo = function(params) {
$('#myModalConfirmUser').modal('show');
$('#closeConfirmUser').unbind('click').click(function () {
$('#myModalConfirmUser').modal('hide');
var params = $rootScope.selectedId;
$scope.getUsers(params);
̶$̶s̶c̶o̶p̶e̶.̶$̶o̶n̶(̶'̶$̶d̶e̶s̶t̶r̶o̶y̶'̶,̶ ̶l̶i̶s̶t̶e̶n̶e̶r̶)̶;̶
});
}
The recommended practice is to broadcast events from $rootScope and receive them on the $scope interested in the event.
is it possible to destroy the listener before the scope gets destroyed?
To remove the listener, simply invoke the de-register function:
deregisterFn();
I am trying to implement a simple bootstrap typeahead where the response is getting fetched via a http call.I am receiving the response perfectly but it seems the latest value from the service call is not getting bound to scope variable from which typeahead is reading.
$scope.onChangeCallBack = function(viewValue) {
var program = $scope.program.name;
var occupancyType = $scope.occupancyType.name;
var isStorage = $scope.isBuildingStorage;
var isFranchise = $scope.isFranchise;
var isLeased = $scope.isLeased;
var isBarBuilding=$scope.isBarBuilding;
console.log("program:"+program+"//occupancyType:"+occupancyType+"//isStorage:"+isStorage+"//isFranchise:"+isFranchise+"//+isBarBuilding"+isBarBuilding+"//viewValue"+viewValue);
var param =
{
searchString: viewValue,
filterCriteria: {
isBar: true/*isBarBuilding*/,
isFranchise: false/*isFranchise*/,
isMercantile: true/*isLeased*/,
program: program,
occupancyType:"tennat"
}
}
var promise = AEBusinessOwnerService.getBuildingClassification(param);
promise.then(function(data) {
console.log(JSON.stringify(data.results));
$sccope.classificationTypeAhead = data.results;
});
};
The search result that get displayed after 4 words are keyed in is visible only after typing the 5th character.I am not sure whats missing.
If I had to guess, I'd guess that AEBusinessOwnerService.getBuildingClassification isn't returning a promise that's integrated with Angular's digest cycle (ie. something based on $q). Try doing this:
promise.then(function(data) {
$scope.$apply(function() {
console.log(JSON.stringify(data.results));
$scope.classificationTypeAhead = data.results;
});
});
This is a supporting answer to Jonathan's but I can't comment yet so:
promise.then(function(data) {
$scope.$apply(function() {
console.log(JSON.stringify(data.results));
$scope.classificationTypeAhead = data.results;
});
});
If I do as above i get the error as Error: [$rootScope:inprog] $digest
already in progress
As the error stated, a $digest is in progress, you can solve it by doing this
if(!$scope.$$phase) {
$scope.$apply(function() {
console.log(JSON.stringify(data.results));
$scope.classificationTypeAhead = data.results;
});
}
New to AngularJS and I guess I don't understand how to call one Promise method from another with the same factory. Every time my code gets to the $http.get within processPerson, I get a Function Expected error in IE, or an Object is not a Function error in Chrome. I've tried reorganizing code many times, multiple factories, etc, and generally get the same error. The only time I can get this to work is if I combine the functions where the processPerson function is embedded within the success of the getPersonnel.
Code:
(function(){
var app = angular.module('hrSite', ['personnel']);
app.controller('PersonnelController', function($scope, personnelFactory){
var personnelPromise = personnelFactory.getPersonnel();
personnelPromise.then(function(personnel){
var perDefs = new Array();
$.each(personnel.data.value, function( i, person ){
var perDef = personnelFactory.processPerson(person);
perDefs.push(perDef);
});
$q.all(perDefs).then(function(){
$scope.personnel = personnel.data.value;
});
});
});
})();
(function(){
var personnelModule = angular.module('personnel', []);
personnelModule.factory('personnelFactory', function($http, $q) {
var getPersonnel = function(){
return $http.get("/sites/Development/_api/web/lists/getbytitle('Personnel')/items");
};
var processPerson = function(person){
var deferred = $q.defer();
$http.get("/sites/Development/_api/web/lists/getbytitle('Personnel Skills')/items?$select=*,Skill/Id,Skill/Title&$filter=PersonId eq '"+person.Id+"'&$expand=Skill").then(function(skills){
person.Skills = skills.data.value;
person.SkillsId = [];
$.each(skills.data.value, function( j, skill ){
person.SkillsId.push(skill.Id);
});
deferred.resolve();
});
return deferred.promise();
};
return {getPersonnel: getPersonnel,
processPerson: processPerson}
});
})();
Nevermind - I figured it out. I was migrating code from a jQuery project and in jQuery, you return a promise like this:
return deferred.promise();
Since Angular has its own deferred feature, $q, I began using that, without realizing that the notation to return a promise was slightly different:
return deferred.promise;
No () in that, which was really screwing things up. Now everything seems to be working fine.
This two functions are part of a controller of a music playlist project i'm working on. After the user selects his files , the prepare function is called to check if each file is valid to play. when done the getIDtags is called to add ID3tags data to each file.
var preparePlaylist = function (files){
var allPromises = [],
currentSongsListLength = $scope.songsList.length || 0;
$.each(files, function (index){
var file = files[index];
file.index = index + currentSongsListLength;
var promiseA = FileValidator2.check(file);
allPromises.push(promiseA);
promiseA
.then (function (file){
SharedService.addSong(file.index, file);
});
});
$q
.all(allPromises)
.then(function () {
console.log('Check Resolved!');
console.log('SharedService updated.');
getID3tags();
});
};
var getID3tags = function (){
var ID3tagsPromises = [];
$.each($scope.songsList, function(index){
var promiseB = ID3tags.getTags($scope.songsList[index]);
ID3tagsPromises.push(promiseB);
promiseB
.then( function (file){
SharedService.addSong(file.index, file);
});
});
$q
.all(ID3tagsPromises)
.then(function () {
console.log('ID3tags Resolved!');
console.log('SharedService updated.');
});
};
How to combine the 2 functions/promises(promiseA, promiseB) into one function with chained promise and still get $q.all when all is done.Thanxs.
So, each function in your file there is to be called one after the other (for this problem domain) then try this.
If functionA returns a promise and functionB returns a promise, functionA's promise can be resolved with the promise from functionB.
function preparePlaylist(){
var finished = $q.defer();
// rest of function body
$q.all(allPromises).then(function(){
//Do whatever you need
finished.resolve(getID3tags());
});
return finished.promise;
function getID3tags(){
var finished = $q.defer();
//rest of function body
$q.all(ID3tagsPromises).then(function(){
//Do whatever you need
finished.resolve('Done both preparePlaylist and getID3tags');
});
return finished.promise;
preparePlaylist.then(function(response){
console.log(response);
});
This might need a little tweaking, but it should work. I've not tested it however. Hope it helps!
Docs for reference: http://docs.angularjs.org/api/ng.$q