$scope.pagination_data = function(page_data){
count = page_data.data.count;
};
console.log("outside count is",count);// this not working
var page = function(){
userService.paginate()
.then(function(user){
$scope.pagination_data(user);
console.log("count is",count);//this is works
});
};
in that code i m using $http service by using that i m getting data aftr that i want a count then i m getting count also but now i want this count variable access in controller but this is not accessible to me. what should i do..?
Actually, both works but you're calling the first one at the wrong time.
The .then() indicates that paginate() returns a promise. Which should be a hint that it is asynchronous.
To prove this, delay calling your first console.log by using setTimeout:
$scope.pagination_data = function(page_data){
count = page_data.data.count;
};
setTimeout(function(){
console.log("outside count is",count);// this should work
}, 5000); // wait 5 seconds before calling the code above
// If 5 seconds is not long enough increase it to 10 or something
var page = function(){
userService.paginate()
.then(function(user){
$scope.pagination_data(user);
console.log("count is",count);//this is works
});
};
What is asynchronous code? Asynchronous simply means that the code will be called later. What paginate().then() does is not call the function(user) function immediately but rather remembers that it is supposed to call function(user) (which then calls your pagination_data function to set the value of count) at a later time. It then continues on running other stuff.
When there's no other code to run, the event loop gets processed and whatever userService.paginate() needs to do asynchronously gets processed.
When whatever userService.paginate() is waiting for finally returns (this may be a network request, user click etc) the function(user) function finally gets called. This in turn calls $scope.pagination_data() which is what assigns the result to the global count variable.
What does that setTimeout() do? Well, it does the same thing I describe above. Instead of calling console.log() immediately it remembers to call it later. Then when 5 seconds (5000 milliseconds) expires, and there is no other javascript code running (this is important because it means javascript can run the event loop), the console.log() finally gets called.
Just define the variable outside.
var count = 0;
$scope.pagination_data = function(page_data){
count = page_data.data.count;
};
console.log("outside count is",count);// this not working
var page = function(){
userService.paginate()
.then(function(user){
$scope.pagination_data(user);
console.log("count is",count);//this is works
});
};
The fist statement only defines the function, it doesn't call it. If you have data to pass to that function call it before logging the count.
// this only defines the function, doesn't call it
$scope.pagination_data = function(page_data){
count = page_data.data.count;
};
console.log("outside count is",count);// count is still unset
var page = function(){
userService.paginate()
.then(function(user){
$scope.pagination_data(user); // this is the call, count will be set
console.log("count is",count);//this will work
});
};
Related
Newbie to JS. I have this function. First, it checks for data in cache. If it's not there, it calls backend for this data and saves it to cache.
function doSomething() {
return getCachedData()
.catch(function() {
return getData()
.then(saveDataToCache);
});
}
I need to test how many times cache and backend are called on the first and the second time the method doSomething is executed. Here is my test:
it('should test', function() {
spyOn(this.service, 'doSomething').andCallThrough();
spyOn(this.service, 'getCachedData').andCallThrough();
spyOn(this.service, 'getData').andCallThrough();
this.service.doSomething();
this.$rootScope.$apply();
expect(this.service.doSomething.callCount).toBe(1);
expect(this.service.getCachedData.callCount).toBe(1);
expect(this.service.getData.callCount).toBe(1);
this.service.doSomething();
this.$rootScope.$apply();
expect(this.service.doSomething.callCount).toBe(2);
expect(this.service.getCachedData.callCount).toBe(2);
expect(this.service.getData.callCount).toBe(1);
});
However, I am getting an error saying that call count for getCachedData and getData is always 0, both the first and the second time.
Changing this.$rootScope.$apply(); to this.$rootScope.$digest(); doesn't improve anything. I also tested it manually and everything seems to be working fine.
I also noticed that if I change the function doSomething as below then the counts for getCachedData are 2 & 2, which is correct.
function doSomething() {
this.getCachedData();
return getCachedData()
.catch(function() {
return getData()
.then(saveDataToCache);
});
}
create an object. for example:
system_metrics ={
cache_calls:0,
backend_calls:0,
reset_cache:function(){this.cache_calls=0;},
reset_backend_calls:function(){this.backend_calls=0;},
add_cache_call:function(){this.cache_calls++;}
add_backend_call:function(){this.cache_calls++;}
}
in
function getCachedData(){
//add this line
system_metrics.add_cache_call();
}
in
function getData(){
//add this line
system_metrics.add_backend_call();
}
I need to test how many times cache and backend are called on the first and the second time the method doSomething is executed
in
function doSomething(){
if(system_metrics.cache_calls === 1){
//the first time the method doSomething is executed
}
if(system_metrics.cache_calls === 2){
//the second time the method doSomething is executed
}
if(system_metrics.backend_calls === 1){
//the first time the method doSomething is executed
}
if(system_metrics.backend_calls === 2){
//the second time the method doSomething is executed
}
}
at anytime during execution.. lets say at the end of the day
you can now check system_metrics.cache_calls to give you total number of cache calls for the day.. thats if you never resetted the cache calls
at anytime during execution you can clear the number of cache calls with system_metrics.reset_cache_calls
if your question is to check how many times cache was called
when doSomething runs for the first time or second time.
if your question is to check how many times backend was called
when doSomething runs for the first time or second time.
add the following to your system_metrics
do_something_calls
add_do_something_call
reset_do_something_call
& add add_do_something_call to your do_something function
i think you get the picture
with this approach you can track any metric that you want anytime that you want to
I was practicing with callback functions and this question is one I can't seem to figure out.
function foo () {
var data = 10;
bar(function (players) {
data = players;
});
return data;
}
function bar (callback) {
setTimeout(callback, 0);
}
var result = foo();
I expected result to be undefined since data = players and there is nothing passed in as players. Since the setTimeout function uses 0 as the delay, shouldn't it run first, and then return data? I looked at the MDN page and there seems to be information on throttling for nested timeouts to >=4ms. Does this also apply in this case?
Since the setTimeout function uses 0 as the delay, shouldn't it run first, and then return data?
No, even with a delay of 0, the callback passed to setTimeout is scheduled to run in the next tick of the event loop.
In other words, the callback is guaranteed to be executed after the current execution ran to completion.
I'm trying to create a callback to my Web API to collect new race data, I've created a setInterval and tested it to see if it does log to the console once as I would expect but for some reason the console is logging twice. I don't understand why.
I am wanting to remove the console.log() inside the if statement and replace that with a call to the server but if it's logging twice i'll receive twice as much information.
var TimeOutID = '';
var TenRaces = 0;
var StartThis = function () {
console.log("Starting run");
//Simulate counting down to next race
TimeOut = new Date().getTime() + 5000;
$('#next').countdown(TimeOut, function (event) {
$(this).html(event.strftime('%H:%M:%S'));
if(event.elapsed) {
//once the countdown timer has elapsed fetch data
console.log("Race: " + TenRaces); // <-- this one is logged twice
}
});
//loop ten races simulating ten different times data is needed
TenRaces++;
if (TenRaces > 10) {
clearInterval(TimeOutID);
}
};
TimeOutID = setInterval(StartThis, 6000);
Why is console.log() running and logging twice?
I'm using the jQuery plugin from http://hilios.github.io/jQuery.countdown/
According to the documentation, the elapsed mode is deliberately designed to continue after the countdown has finished. Therefore I think it's looping twice before the TenRaces var iterates. It would just keep logging forever if you didn't iterate that var.
Do the log/fetch data on the finish.countdown event instead, this triggers just once, when the countdown finishes. See documentation:
countdown documentation
E.g.
$('div#clock').countdown(finalDate)
.on('finish.countdown', callback);
While waiting for the back end devs to implement a "cancel all" feature, which cancels all tasks tracked by the back end, I am attempting to makeshift it by cancelling each individual task. The cancel REST service accepts an ID in the form of a data object {transferID: someID}.
I use a FOR loop to iterate over an array of IDs that I have stored elsewhere. Anticipating that people MAY end up with dozens or hundreds of tasks, I wanted to implement a small delay that will theoretically not overflow the number of HTTP requests the browser can handle and will also reduce a blast of load on the back end CPU. Here is some code with comments for the purpose of this discussion:
ta.api.cancel = function (taskArray, successCallback, errorCallback) {
// taskArray is ["task1","task2"]
// this is just the latest attempt. I had an attempt where I didn't bother
// with this and the results were the same. I THOUGHT there was a "back image"
// type issue so I tried to instantiate $.ajax into two different variables.
// It is not a back image issue, though, but one to do with setTimeout.
ta.xhrObjs = ta.xhrObjs || {};
for (var i = 0; i < taskArray.length; i++) {
console.log(taskArray); // confirm that both task1 and task2 are there.
var theID = taskArray[i];
var id = {transferID: theID}; // convert to the format understood by REST
console.log(id); // I see "task1" and then "task2" consecutively... odd,
// because I expect to see the "inside the setTimeout" logging line next
setTimeout(function () {
console.log('inside the setTimeout, my id is: ')
console.log(id.transferID);
// "inside the setTimeout, my id is: task2" twice consecutively! Y NO task1?
ta.xhrObjs[theID] = doCancel(id);
}, 20 * i);
}
function doCancel(id) {
// a $.Ajax call for "task2" twice, instead of "task1" then "task2" 20ms
// later. No point debugging the Ajax (though for the record, cache is
// false!) because the problem is already seen in the 'setTimeout' and
// fixed by not setting a timeout.
}
}
Thing is: I know setTimeout makes the containing function execute asynchronously. If I take out the timeout, and just call doCancel in the iterator, it will call it on task1 and then task2. But although it makes the call async, I don't understand why it just does task2 twice. Can't wrap my head around it.
I am looking for a way to get the iterator to make the Ajax calls with a 20ms delay. But I need it to call on both! Anybody see a glaring error that I can fix, or know of a technique?
You must wrap your function setTimeout and pass the id variable into it, like this:
(function(myId, i) {
setTimeout(function () {
console.log('inside the setTimeout, my id is: ', myId);
}, 20 * i);
}(theId, i));
This pattern does not create a unique variable1 for each instance of the loop as one might expect.
function () {
for (var i = 0; i < length; i++) {
var variable1;
}
}
In javascript variables are "hoisted". To quote Mozilla:
"Because variable declarations (and declarations in general) are
processed before any code is executed, declaring a variable anywhere
in the code is equivalent to declaring it at the top."
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var
So it should be re-written as:
function () {
var variable1;
for (var i = 0; i < length; i++) {
}
}
What this means is that after the loop has finished, any asynchronous callbacks that reference this variable will see the last value of the loop.
I have this function:
isAuthenticated = (): boolean => {
xxx
};
I am using AngularJS and I would like to know how can I make a function such as
keepCheckingAuthentication()
That will call the is Authenticated() function every 60 seconds?
There’s a setInterval function that will call any code with given time interval in ms:
var intervalID = setInterval(function() { console.log('Works!') }, 1000);
Later you can cancel the timer using clearInterval(intervalID).
If isAuthenticated can be modified to actually make a request to call the server in order to check authentication, and can return a promise that resolves or rejects when this is done, then I would do something like
var keepCheckingAuthentication = function() {
return isAuthenticated().catch(angular.noop).then(function(isAuth) {
// Can do something different if isAuth == false
return $timeout(keepCheckingAuthentication, 60 * 1000);
});
});
Note the call to catch. This effectively converts any rejections to a success, so the next then callback runs in every case.
Using something like this rather than $setInterval means there will always be 60 seconds between responses from the server, rather than requests made. On a slower connection, or an overloaded server, this means there is a lower chance of adding to the overloaded connection or server, as you're sure the previous request has finished before sending off another one.
you can probably use $interval function (wrapper of window.setInterval() in AngularJS)?
The documentation of $interval function is here
In your case keepCheckingAuthentication() is the function and you can adjust the other parameters accoding to your needs? Does this help?
example:
$interval(myFunctionAtInterval, 5000) // Scheduled for every 5 seconds, for instance
funtion myFunctionAtInterval() {...}
I tend to avoid setInterval whenever I can, i.e. always (Paul Irish talks about this in this video).
What I do is wrap a setTimeout in a function that recursively calls itself (with a condition that allows me to easily stop, or to let the data decide when it's not needed anymore).
var condition = true;
$scope.count = 1;
function myFunc(){
$scope.count += 1;
}
var timer = function(){
myFunc();
if( condition ){
$timeout(timer, 1000);
}
};
timer();
I am using angular built in $timeout here as it's always suggested.
A demo
use $interval.this code will help you:
var callefunc=function() {
console.log('hey i am calle');
}
$scope.caller=function(){
var stop = $interval(callefunc, 1000);
}
here you can call a caller function when you want to start function callefunc on interval of 1 second .