callback function gives an error - angularjs - javascript

I am using the $timeout service in angular to decrease a variable from 100 down to 1 every 1/10 seconds.
I know there is a much easier way to do this using the $interval service and I've done it. But, here, specifically, I am testing a callback in angular - not really trying to decrease a variable from 100 down to 1 every 1/10 seconds.
Specifically, I want the callback to be called when the $timeout function is sleeping (for 1/10 seconds)
My question is why I get an "undefined is not a function" error when using a callback. I have included the JS code below. It's also on JSbin here
Here's the JS code:
var testApp = angular.module('testApp', []);
testApp.controller('testCtrl', ['$scope', '$timeout', function($scope, $timeout) {
var q = 100;
function decreaseQ(callback) {
$scope.someThing = q;
if(q>0){ $timeout(decreaseQ, 100);q--;}
callback();
}
decreaseQ(function(){console.log("Hello World");});
}]);

That is because after the first invocation of decreaseQ with a function argument you are calling decreaseQ without any argument by setting it in the timeout.But you expect a callback and you invoke the function decreaseQ() which causes the error.
Instead you would just need to pass the function as callback.
if (q-- > 0) {
$timeout(function() {
decreaseQ(callback); //Pass the callback as argument
}, 100);
}
Or use bound function
$timeout(angular.bind(null, decreaseQ, callback), 100);
or just do not run if there is no callback provided by adding a check.
if(angular.isFunction(callback)) { callback(); }
Or use the dummy anonymous function
(callback||angular.noop)();

Related

$save().then on Angular $resource doesn't wait for the service response

I have some controller and a function called to obtain some value from a REST WCF web service:
fooBar.controller('fooCtrl',
function fooCtrl($scope, $http, $resource) {
$scope.someOnClickEvent = function () {
GetSomething('a','b','c');
}
}
);
function GetSomething($scope, $resource, a, b, c) {
var ServiceHandle = $resource('some/addr');
var serviceHandle = new ServiceHandle();
serviceHandle.a = a;
serviceHandle.b = b;
serviceHandle.c = c;
serviceHandle.$save().then(function (result) {
console.log('So response should be ready');
$scope.result = result.ValueFromService;
});
}
As far as I know $save() returns promise and function inside .then should be called right after response is returned by the server. In my case it's called imediately.
If service returns true I'm going to show some popup, so I need this value to be returned before conditional instruction is executed.
Version of Angular is 1.4.9.
I've analysed code and its behavior and I'm wrong obviously. Maybe I should delete this question, but I believe it can help someone to understand similar problems.
Function inside .then is in fact called after a response comes from the server. It can be verified using for instance Chrome's developer tools (namely tab network).
However if just after calling GetSomething function we want to access a $scope.result we are making a great mistake. $scope.result will be undefined as long as function inside .then won't be executed. To use a value returned from a service we must do it inside .then function or in a function called by it.

Javascript Functions Inside Parameters?

I come from a background in C/C#/Java and PHP so I'm used to those standards of coding, where a function is defined using function(parameters) { ... return x}
But lately I've been learning some JS libraries like Angular/Node and come across functions (or maybe there not?) with another function inside the parameters, like this:
app.controller('MainController', ['$scope', 'forecast', function($scope, forecast) {
forecast.success(function(data) {
$scope.fiveDay = data;
});
}]);
app.factory('forecast', ['$http', function($http) {
return $http.get('https://s3.amazonaws.com/codecademy- content/courses/ltp4/forecast-api/forecast.json')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
It just confuses me and goes against what I've learned about functions. Is this convention only used in scripting languages? I seems like they go
function(parameter, function(parameter) { do something; });
Anyone explain why this is used or if it does anything than a normal function?
Thanks.
In Javascript a variable can return a function, which could return another function, pretty much endlessly.
For example:
var myFunction = function() {
return getAnswer();
}
var getAnswer = function() {
return "Hello world!";
}
console.log(myFunction); will return
var myFunction = function() {
return getAnswer();
}
and console.log(myFunction()); will return
"Hello world!"
So App.controller is a variable that is part of the app object, but it's a function so you are passing in parameters, some of which can be a function.
https://jsfiddle.net/Lu46sf2v/2/
Is a way of passing a function as an argument to another function. In C, you can define a function, and then pass it to another function as a pointer. In Javascript, you can just define the function right there. C# can do that too.
In javascript, functions are first-class objects, meaning you can attach parameters to them, rename them, create them on the fly, or pass them like normal objects.
In node.js, for instance, most libraries specify a function to call after some operation completes. You can either point it to an existing function by name, or you can make an anonymous one and stuff it into the parameters.
In Javascript, functions are first-class functions, this means you can pass a function as an argument, or return a new function inside a function.
What you're seeing is a callback, you receive that function as an argument and execute sometime later when you need.
E.g: A function that will be called when you click at a button
var btn = document.querySelector('btn');
btn.addEventListener('click', function() {
alert("I was clicked");
});
This code will add a listener to the button, when the click is fired it'll call the callback function.

$scope or $http vs. response or reason in AngularJS

I started learning Angular JS two hours ago and saw this in the tutorial:
var app = angular.module("githubViewer", []);
var MainController = function($scope, $http){
var onUserComplete = function(response){
$scope.user = response.data;
};
var onError = function(reason){
$scope.error = "Failed to get the user info.";
};
var promise = $http.get("https://api.github.com/users/someone");
promise.then(onUserComplete, onError);
};
app.controller("MainController", MainController);
I understand $scope/$http is native to Angular but what about the response/reason? How are they passed to the function?
Those are the callback functions - onUserComplete and onError, which are called when the promise returned by $http.get() function is resolved. The callback functions are passed response returned by the completion of $http.get() invocation. The parameter in the function is that response.
#Rohit Jain is right.
This is much more a related to Javascript then Angular.
CallBack are often used in JS.
Here is a quick exemple to understand how CallBack works
function mainFunc(mycallBack){
mycallBack()
}
function onSomething(){
alert("hi");
}
mainFunc(onSomething);
http://plnkr.co/edit/Ud1E6Wbns1EnItVI8Xg7?p=preview
I hope it helps.
Regards,
Eric

why the need to use 'timeout' in angular

This is probably a total newb question...apologies, but I can't get my head around it.
In a lot of angular documentation/examples I see asynchronous functions wrapped in 'timeout' blocks. Many are wrapped in setTimeout() and require the explicit use of
if (!$scope.$$phase) {
$scope.$apply();
}
Given that angular provides $timeout, the above code just seems outdated or wrong and within angular the use of $timeout should always be preferred. However, I digress.
Here is a snippet of some example code taken from: http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/
var myModule = angular.module('myModule', []);
// From this point on, we'll attach everything to 'myModule'
myModule.factory('HelloWorld', function($timeout) {
var getMessages = function(callback) {
$timeout(function() {
callback(['Hello', 'world!']);
}, 2000);
};
return {
getMessages: getMessages
};
});
I see this wrapping of code in timeout blocks everywhere particularly related to asynchronous calls. But can someone explain why this is needed? Why not just change the code above to:
var myModule = angular.module('myModule', []);
// From this point on, we'll attach everything to 'myModule'
myModule.factory('HelloWorld', function() {
var getMessages = function(callback) {
callback(['Hello', 'world!']);
};
return {
getMessages: getMessages
};
});
Why wouldn't the code snippet above work just fine?
The use of $timeout or $interval is to implicitly trigger a digest cycle. The process is as follows:
Execute each task in the callback function
Call $apply after each task is executed
$apply triggers a digest cycle
An alternative is to inject $rootScope and call $rootScope.$digest() if you are using services that don't trigger a $digest cycle.
Angular uses a dirty-checking digest mechanism to monitor and update values of the scope during
the processing of your application. The digest works by checking all the values that are being
watched against their previous value and running any watch handlers that have been defined for those
values that have changed.
This digest mechanism is triggered by calling $digest on a scope object. Normally you do not need
to trigger a digest manually, because every external action that can trigger changes in your
application, such as mouse events, timeouts or server responses, wrap the Angular application code
in a block of code that will run $digest when the code completes.
References
AngularJS source: intervalSpec.js
AngularJS source: timeoutSpec.js
$q deferred.resolve() works only after $timeout.flush()
AngularJS Documentation for inprog | Digest Phases
The $timeout in your example is probably used just to simulate an async function, like $http.get. As to why $timeout and not setTimeout: $timeout automatically tells angular to update the model, without the need to call $scope.$apply()
Also, consider the following example:
$scope.func = function(){
$scope.showSomeLoadingThing = true;
//Do some long-running stuff
$scope.showSomeLoadingThing = false;
}
No loading thingy will be shown, you would have to write it like this:
$scope.func = function(){
$scope.showSomeLoadingThing = true;
$timeout(function(){
//Do some long-running stuff
$scope.showSomeLoadingThing = false;
});
}

Angular's $rootScope.$digest

Reading this excellent book, Mastering Web Development in AngularJS, I ran across this code:
var Restaurant = function ($q, $rootScope) {
var currentOrder;
this.takeOrder = function (orderedItems) {
currentOrder = {
deferred:$q.defer(),
items:orderedItems
};
return currentOrder.deferred.promise;
};
this.deliverOrder = function() {
currentOrder.deferred.resolve(currentOrder.items);
$rootScope.$digest();
};
this.problemWithOrder = function(reason) {
currentOrder.deferred.reject(reason);
$rootScope.$digest();
};
My understanding is that the $rootScope.$digest(); calls are made in order to alert Angular that the Promise's state has been updated.
Is my understanding correct? Also, is it necessary to make the above $rootScope.$digest(); calls?
$scope.$digest() is what processes all of the $watch events that are on the current and children scope. It essentially manually tells the scope to check if a scope variable has changed. You don't generally want to use this when you are inside of a controller or a directive, because the $scope.$apply() function calls the $digest anyway and it is called when you mutate a scope variable.
Checkout this link for an example.
You don't need a $rootScope.$digest here because resolving/rejecting the promise will fire a $rootScope.$digest internally, as $interval,$timeout,and $http (after request finished) do that for you. And this $digest can throw errors of $digest already in progress.

Categories